瑞吉外卖实战项目全攻略——功能补充篇

瑞吉外卖实战项目全攻略——功能补充篇

该系列将记录一份完整的实战项目的完成过程,该篇属于功能补充篇

案例来自B站黑马程序员Java项目实战《瑞吉外卖》,请结合课程资料阅读以下内容

该篇我们将完成课程中未完成的所有功能,包括以下功能:

  • 菜品单独启售停售和批量启售停售(管理端)
  • 菜品批量删除(管理端)
  • 套餐管理启售停售(管理端)
  • 套餐管理修改(管理端)
  • 订单明细展示(管理端)
  • 后台订单状态修改(管理端)
  • 套餐详细展示(用户端)
  • 购物车数量减少(用户端)
  • 查看订单(用户端)
  • 再来一单(用户端)
  • 地址功能补充(用户端)
  • 退出账户(用户端)

菜品单独启售停售和批量启售停售(管理端)

我们将代码开发分为三部分

需求分析

功能解释:

修改菜品的售卖状况

请求展示:

# 单个启售
url://localhost:8080/dish/status/1?ids=1413384757047271425,1413385247889891330
Method:POST

# 单个停售
url://localhost:8080/dish/status/0?ids=1413384757047271425,1413385247889891330
Method:POST

# 批量启售
url://localhost:8080/dish/status/1?ids=1413384757047271425,1413385247889891330
Method:POST

# 批量停售
url://localhost:8080/dish/status/0?ids=1413384757047271425,1413385247889891330
Method:POST

代码实现

代码展示:

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.DishServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {

    @Autowired
    private DishServiceImpl dishService;

     /**
     * 启售,批量启售
     * @param ids
     * @return
     */

    @PostMapping("/status/1")
    public Result<String> openStatus(Long[] ids) {

        for (Long id : ids
        ) {
            Dish dish = dishService.getById(id);
            dish.setStatus(1);
            dishService.updateById(dish);
        }

        return Result.success("修改成功");
    }

    
     /**
     * 停售,批量停售
     * @param ids
     * @return
     */
    @PostMapping("/status/0")
    public Result<String> closeStatus(Long[] ids) {

        for (Long id : ids
        ) {
            Dish dish = dishService.getById(id);
            dish.setStatus(0);
            dishService.updateById(dish);
        }

        return Result.success("修改成功");
    }
}

实际测试

返回菜品页面,点击若干菜品,进行三个方法的测试,实现即可

菜品批量删除(管理端)

我们将代码开发分为三部分

需求分析

功能解释:

删除菜品本身

请求展示:

# 批量删除
url://localhost:8080/dish?ids=1583025958761824258
Method:DELETE

代码实现

代码展示:

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.DishServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {

    @Autowired
    private DishServiceImpl dishService;

    /**
     * 批量删除
     * @param ids
     * @return
     */
    @DeleteMapping
    public Result<String> deleteByIds(Long[] ids){

        for (Long id:ids
             ) {
            dishService.removeById(id);
        }

        return Result.success("删除成功");
    }
}

实际测试

回到菜品管理页面,进行批量删除,删除成功即为功能开发成功

套餐管理启售停售(管理端)

我们将代码开发分为三部分

需求分析

功能解释:

修改套餐的售卖状况

请求展示:

// 单个停售
请求 URL: //localhost:8080/setmeal/status/0?ids=1415580119015145474
请求方法: POST

// 多个停售
请求 URL: //localhost:8080/setmeal/status/0?ids=1415580119015145474,1583260610277715970
请求方法: POST

// 单个启售
请求 URL: //localhost:8080/setmeal/status/1?ids=1415580119015145474
请求方法: POST

// 多个启售
请求 URL: //localhost:8080/setmeal/status/1?ids=1415580119015145474,1583260610277715970
请求方法: POST

代码实现

代码展示:

package com.qiuluo.reggie.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Setmeal;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.dto.SetmealDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.SetmealDishServiceImpl;
import com.qiuluo.reggie.service.impl.SetmealServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/setmeal")
public class SetmealController {

    @Autowired
    private SetmealServiceImpl setmealService;

    @Autowired
    private SetmealDishServiceImpl setmealDishService;

    @Autowired
    private CategoryServiceImpl categoryService;

    // 其实还可以整合成一个方法,url写为/status,读取后面的值设置为status,根据status对ids进行操作即可
    
    @PostMapping("/status/0")
    public Result<String> closeStatus(@RequestParam List<Long> ids){

        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.in(Setmeal::getId,ids);

        List<Setmeal> setmeals = setmealService.list(queryWrapper);

        for (Setmeal setmeal:setmeals
        ) {
            setmeal.setStatus(0);
            setmealService.updateById(setmeal);
        }

        return Result.success("修改成功");
    }

    @PostMapping("/status/1")
    public Result<String> openStatus(@RequestParam List<Long> ids){

        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.in(Setmeal::getId,ids);

        List<Setmeal> setmeals = setmealService.list(queryWrapper);

        for (Setmeal setmeal:setmeals
        ) {
            setmeal.setStatus(1);
            setmealService.updateById(setmeal);
        }

        return Result.success("修改成功");
    }

}

实际测试

回到套餐管理页面,点击启售停售,操作成功即为功能开发成功

套餐管理修改(管理端)

我们将代码开发分为三部分

需求分析

功能解释:

该功能由两部分组成,一方面需要根据id将该套餐的信息回显在页面,一方面需要将修改后的套餐信息保存起来

请求展示:

# 回显操作
请求 URL: //localhost:8080/setmeal/1415580119015145474
请求方法: GET

# 修改操作
请求 URL: //localhost:8080/setmeal
请求方法: PUT

代码实现

回显操作代码展示:

// 回显操作

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Setmeal;
import com.qiuluo.reggie.domain.SetmealDish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.dto.SetmealDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.SetmealDishServiceImpl;
import com.qiuluo.reggie.service.impl.SetmealServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/setmeal")
public class SetmealController {

    @Autowired
    private SetmealServiceImpl setmealService;

    @Autowired
    private SetmealDishServiceImpl setmealDishService;

    @Autowired
    private CategoryServiceImpl categoryService;

    /**
    * 回显操作
    */
    @GetMapping("/{id}")
    public Result<SetmealDto> getById(@PathVariable Long id){

        // 我们需要把setmealDto返回回去,定义一个新的setmealDto用于保存数据
        SetmealDto setmealDto = new SetmealDto();

        // 将普通数据传入

        Setmeal setmeal = setmealService.getById(id);

        BeanUtils.copyProperties(setmeal,setmealDto);

        // 将菜品信息传递进去

        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId,id);

        List<SetmealDish> list = setmealDishService.list(queryWrapper);

        setmealDto.setSetmealDishes(list);

        // 返回setmealDto即可
        return Result.success(setmealDto);
    }
}

修改操作代码展示:

// 1.修改操作——业务层接口定义

package com.qiuluo.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.qiuluo.reggie.domain.Setmeal;
import com.qiuluo.reggie.dto.SetmealDto;

import java.util.List;

public interface SetmealService extends IService<Setmeal> {

    /**
     * 修改操作
     * @param setmealDto
     */
    public void updateWithDish(SetmealDto setmealDto);

}
// 2.修改操作——业务层功能实现

package com.qiuluo.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiuluo.reggie.common.CustomException;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Setmeal;
import com.qiuluo.reggie.domain.SetmealDish;
import com.qiuluo.reggie.dto.SetmealDto;
import com.qiuluo.reggie.mapper.SetmealMapper;
import com.qiuluo.reggie.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper,Setmeal> implements SetmealService {

    @Autowired
    private SetmealDishServiceImpl setmealDishService;

    /**
     * 修改操作
     * @param setmealDto
     */
    public void updateWithDish(SetmealDto setmealDto){

        // 首先修改套餐上的信息
        this.updateById(setmealDto);

        // 修改内部菜品操作(同样先删除再添加)

        // 删除操作
        Long setmealId = setmealDto.getId();

        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId,setmealId);

        setmealDishService.remove(queryWrapper);

        // 新填操作

        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();

        setmealDishService.saveBatch(setmealDishes);

    }

}
// 3.服务层代码实现

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Setmeal;
import com.qiuluo.reggie.domain.SetmealDish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.dto.SetmealDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.SetmealDishServiceImpl;
import com.qiuluo.reggie.service.impl.SetmealServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/setmeal")
public class SetmealController {

    @Autowired
    private SetmealServiceImpl setmealService;

    @PutMapping
    public Result<String> update(@RequestBody SetmealDto setmealDto){

        setmealService.updateById(setmealDto);

        return Result.success("修改成功");

    }
}

实际测试

我们需要注意两处测试内容:

  • 点击修改功能后,打开修改页面,页面出现相关信息
  • 点击修改完成功能后,页面信息内容成功修改即可

订单明细展示(管理端)

我们将代码开发分为三部分

需求分析

功能解释:

返回类型大部分都是Orders的属性,但含有特殊属性UserName需要采用DTO实现

请求展示:

# 订单展示
请求 URL: //localhost:8080/order/page?page=1&pageSize=10
请求方法: GET

代码实现

代码展示:

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiuluo.reggie.common.BaseContext;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.OrderDetail;
import com.qiuluo.reggie.domain.Orders;
import com.qiuluo.reggie.domain.ShoppingCart;
import com.qiuluo.reggie.domain.User;
import com.qiuluo.reggie.dto.OrdersDto;
import com.qiuluo.reggie.service.OrderService;
import com.qiuluo.reggie.service.impl.OrderDetailServiceImpl;
import com.qiuluo.reggie.service.impl.ShoppingCartServiceImpl;
import com.qiuluo.reggie.service.impl.UserServiceImpl;
import com.sun.org.apache.xpath.internal.operations.Or;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单
 */
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderDetailServiceImpl orderDetailService;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private ShoppingCartServiceImpl shoppingCartService;

    /**
     * 后台回显
     * @param page
     * @param pageSize
     * @param number
     * @param beginTime
     * @param endTime
     * @return
     */
    @GetMapping("/page")
    public Result<Page> pagePC(int page, int pageSize, Long number, Date beginTime,Date endTime){

        // 定制基本Page
        Page<Orders> pageInfo = new Page<>(page,pageSize);

        // 定制带有名字的特殊Orders
        Page<OrdersDto> ordersDtoPage = new Page<>();

        // 书写限制条件
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(number != null,Orders::getId,number);
        if (beginTime != null && endTime != null){
            queryWrapper.between(Orders::getOrderTime,beginTime,endTime);
        }

        orderService.page(pageInfo, queryWrapper);

        // 普通赋值
        BeanUtils.copyProperties(pageInfo,ordersDtoPage,"records");

        // 订单赋值
        List<Orders> records = pageInfo.getRecords();

        List<OrdersDto> ordersDtoList = records.stream().map((item) -> {

            // 新创内部元素
            OrdersDto ordersDto = new OrdersDto();

            // 普通值赋值
            BeanUtils.copyProperties(item,ordersDto);

            // 特殊值赋值
            Long userId = item.getUserId();

            User user = userService.getById(userId);

            ordersDto.setUserName(user.getName());

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

        // 完成dishDtoPage的results的内容封装
        ordersDtoPage.setRecords(ordersDtoList);

        return Result.success(ordersDtoPage);
    }
}

实际测试

打开订单界面,订单数据全部展示即为功能开发成功

后台订单状态修改(管理端)

我们将代码开发分为三部分

需求分析

功能解释:

将订单的状态进行修改,订单状态分为未支付,未派送,已派送,已完成

请求展示:

# 订单status状态修改
请求 URL: //localhost:8080/order
请求方法: PUT

代码实现

代码展示:

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiuluo.reggie.common.BaseContext;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.OrderDetail;
import com.qiuluo.reggie.domain.Orders;
import com.qiuluo.reggie.domain.ShoppingCart;
import com.qiuluo.reggie.domain.User;
import com.qiuluo.reggie.dto.OrdersDto;
import com.qiuluo.reggie.service.OrderService;
import com.qiuluo.reggie.service.impl.OrderDetailServiceImpl;
import com.qiuluo.reggie.service.impl.ShoppingCartServiceImpl;
import com.qiuluo.reggie.service.impl.UserServiceImpl;
import com.sun.org.apache.xpath.internal.operations.Or;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单
 */
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderDetailServiceImpl orderDetailService;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private ShoppingCartServiceImpl shoppingCartService;

    /**
     * 状态修改
     * @param orders
     * @return
     */
    @PutMapping
    public Result<String> beginSend(@RequestBody Orders orders){

        orderService.updateById(orders);

        return Result.success("修改成功");
    }
}

实际测试

点击状态修改对应的相关按钮,订单状态发生改变即可

套餐详细展示(用户端)

我们将代码开发分为三部分

需求分析

功能解释:

点击菜品图片,展示菜品的详细介绍

请求展示:

# 套餐详细展示
请求 URL: //localhost:8080/setmeal/dish/1415580119015145474
请求方法: GET

代码实现

代码展示:

package com.qiuluo.reggie.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.Category;
import com.qiuluo.reggie.domain.Dish;
import com.qiuluo.reggie.domain.Setmeal;
import com.qiuluo.reggie.domain.SetmealDish;
import com.qiuluo.reggie.dto.DishDto;
import com.qiuluo.reggie.dto.SetmealDto;
import com.qiuluo.reggie.service.impl.CategoryServiceImpl;
import com.qiuluo.reggie.service.impl.DishServiceImpl;
import com.qiuluo.reggie.service.impl.SetmealDishServiceImpl;
import com.qiuluo.reggie.service.impl.SetmealServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/setmeal")
public class SetmealController {

    @Autowired
    private DishServiceImpl dishService;

    @Autowired
    private SetmealServiceImpl setmealService;

    @Autowired
    private SetmealDishServiceImpl setmealDishService;

    @Autowired
    private CategoryServiceImpl categoryService;

    /**
     * 点击套餐图片查看套餐具体内容
     * 前端主要要展示的信息是:套餐中菜品的基本信息,图片,菜品描述,以及菜品的份数
     * @param SetmealId
     * @return
     */
    @GetMapping("/dish/{id}")
    public Result<List<DishDto>> dish(@PathVariable("id") Long SetmealId) {
        
        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId, SetmealId);
        
        // 获得数据
        List<SetmealDish> list = setmealDishService.list(queryWrapper);

        List<DishDto> dishDtos = list.stream().map((setmealDish) -> {
            DishDto dishDto = new DishDto();

            // 基本信息拷贝
            BeanUtils.copyProperties(setmealDish, dishDto);
            
            // 设置其他信息
            Long dishId = setmealDish.getDishId();
            Dish dish = dishService.getById(dishId);
            BeanUtils.copyProperties(dish, dishDto);

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

        return Result.success(dishDtos);
    }
}

实际测试

点击移动端页面中的套餐图片,弹出套餐详情弹框即可

购物车数量减少(用户端)

我们将代码开发分为三部分

需求分析

功能解释:

点击购物车的减号,购物车中菜品数量减少

请求展示:

# 减少数量
请求 URL: //localhost:8080/shoppingCart/sub
请求方法: POST

代码实现

代码展示:

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiuluo.reggie.common.BaseContext;
import com.qiuluo.reggie.common.CustomException;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.ShoppingCart;
import com.qiuluo.reggie.service.impl.ShoppingCartServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Slf4j
@RestController
@RequestMapping("/shoppingCart")
public class ShoppingCartController {

    @Autowired
    private ShoppingCartServiceImpl shoppingCartService;

    /**
     * 数值删减
     * @param shoppingCart
     * @return
     */
    @PostMapping("/sub")
    public Result<ShoppingCart> sub(@RequestBody ShoppingCart shoppingCart){
        // 设置用户
        Long currentId = BaseContext.getCurrentId();
        shoppingCart.setUserId(currentId);

        // 基本查找条件
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(ShoppingCart::getUserId,currentId);

        Long dishId = shoppingCart.getDishId();

        // 判断菜品或者套餐

        if(dishId != null){
            // 购物车为菜品
            queryWrapper.eq(ShoppingCart::getDishId,shoppingCart.getDishId());
        }else {
            // 购物车为套餐
            queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId());
        }

        // 判断个数,如果为正数,减一;如果为0,抛出异常
        ShoppingCart shoppingCartServiceOne = shoppingCartService.getOne(queryWrapper);
        Integer number = shoppingCartServiceOne.getNumber();

        if (number != 0){
            shoppingCartServiceOne.setNumber(number - 1);
            shoppingCartService.updateById(shoppingCartServiceOne);
        }else {
            shoppingCartService.removeById(shoppingCartServiceOne);
        }

        return Result.success(shoppingCartServiceOne);
    }
}

实际测试

点击购物车的减号,菜品数量减少即为功能开发成功

查看订单(用户端)

我们将代码开发分为三部分

需求分析

功能解释:

点开历史订单,可以查看到自己之前的订单信息

请求展示:

# 查看订单(菜品)
请求 URL: //localhost:8080/order/userPage?page=1&pageSize=5
请求方法: GET

# 查看订单(套餐)
请求 URL: //localhost:8080/order/userPage?page=2&pageSize=5
请求方法: GET

代码实现

代码展示:

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiuluo.reggie.common.BaseContext;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.OrderDetail;
import com.qiuluo.reggie.domain.Orders;
import com.qiuluo.reggie.domain.ShoppingCart;
import com.qiuluo.reggie.domain.User;
import com.qiuluo.reggie.dto.OrdersDto;
import com.qiuluo.reggie.service.OrderService;
import com.qiuluo.reggie.service.impl.OrderDetailServiceImpl;
import com.qiuluo.reggie.service.impl.ShoppingCartServiceImpl;
import com.qiuluo.reggie.service.impl.UserServiceImpl;
import com.sun.org.apache.xpath.internal.operations.Or;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单
 */
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderDetailServiceImpl orderDetailService;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private ShoppingCartServiceImpl shoppingCartService;

    /**
     * 查看手机版历史纪录
     * @param page
     * @param pageSize
     * @return
     */
    @GetMapping("/userPage")
    public Result<Page> pagePhone(int page,int pageSize){

        // 新创返回类型Page
        Page<Orders> pageInfo = new Page<>(page,pageSize);
        Page<OrdersDto> ordersDtoPage = new Page<>();

        // 用户ID
        Long currentId = BaseContext.getCurrentId();

        // 原条件写入
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Orders::getUserId,currentId);
        queryWrapper.orderByDesc(Orders::getOrderTime);

        orderService.page(pageInfo,queryWrapper);

        // 普通赋值
        BeanUtils.copyProperties(pageInfo,ordersDtoPage,"records");

        // 订单赋值
        List<Orders> records = pageInfo.getRecords();

        List<OrdersDto> ordersDtoList = records.stream().map((item) -> {

            // 新创内部元素
            OrdersDto ordersDto = new OrdersDto();

            // 普通值赋值
            BeanUtils.copyProperties(item,ordersDto);

            // 菜单详情赋值
            Long itemId = item.getId();

            LambdaQueryWrapper<OrderDetail> orderDetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
            orderDetailLambdaQueryWrapper.eq(OrderDetail::getOrderId,itemId);

            int count = orderDetailService.count(orderDetailLambdaQueryWrapper);

            List<OrderDetail> orderDetailList = orderDetailService.list(orderDetailLambdaQueryWrapper);

            ordersDto.setSumNum(count);

            ordersDto.setOrderDetails(orderDetailList);

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

        // 完成dishDtoPage的results的内容封装
        ordersDtoPage.setRecords(ordersDtoList);

        return Result.success(ordersDtoPage);
    }
}

实际测试

点开历史订单,关于自己的历史订单展现即可

再来一单(用户端)

我们将代码开发分为三部分

需求分析

功能解释:

当订单处于已完成的阶段,手机端出现再来一单的按钮,点击后跳转购物车并将该订单的菜品加入购物车

请求展示:

# 再来一单
请求 URL: //localhost:8080/order/again
请求方法: POST

代码实现

我们需要对购物车进行一些简单的操作,因而我们需要先构造一个简单方法:

// 业务层实现(业务层接口这里不再展示)

package com.qiuluo.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiuluo.reggie.common.BaseContext;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.ShoppingCart;
import com.qiuluo.reggie.mapper.ShoppingCartMapper;
import com.qiuluo.reggie.service.ShoppingCartService;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.DeleteMapping;

@Service
public class ShoppingCartServiceImpl extends ServiceImpl<ShoppingCartMapper, ShoppingCart> implements ShoppingCartService {

    public Result<String> clean(){

        // 进行用户比对
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());

        // 删除即可
        this.remove(queryWrapper);

        return Result.success("清空成功");

    }
}

然后我们正式进入代码实现环节:

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiuluo.reggie.common.BaseContext;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.OrderDetail;
import com.qiuluo.reggie.domain.Orders;
import com.qiuluo.reggie.domain.ShoppingCart;
import com.qiuluo.reggie.domain.User;
import com.qiuluo.reggie.dto.OrdersDto;
import com.qiuluo.reggie.service.OrderService;
import com.qiuluo.reggie.service.impl.OrderDetailServiceImpl;
import com.qiuluo.reggie.service.impl.ShoppingCartServiceImpl;
import com.qiuluo.reggie.service.impl.UserServiceImpl;
import com.sun.org.apache.xpath.internal.operations.Or;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单
 */
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderDetailServiceImpl orderDetailService;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private ShoppingCartServiceImpl shoppingCartService;

    //客户端点击再来一单
    /**
     * 我们需要将订单内的菜品重新加入购物车,所以在此之前我们需要将购物车清空(业务层实现方法)
     * 
     * 
     */
    @PostMapping("/again")
    public Result<String> againSubmit(@RequestBody Map<String,String> map){
        // 获得ID
        String ids = map.get("id");

        long id = Long.parseLong(ids);

        // 制作判断条件
        LambdaQueryWrapper<OrderDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderDetail::getOrderId,id);
        
        //获取该订单对应的所有的订单明细表
        List<OrderDetail> orderDetailList = orderDetailService.list(queryWrapper);

        //通过用户id把原来的购物车给清空
        shoppingCartService.clean();

        //获取用户id
        Long userId = BaseContext.getCurrentId();
        
        // 整体赋值
        List<ShoppingCart> shoppingCartList = orderDetailList.stream().map((item) -> {
       		
            // 以下均为赋值操作
            
            ShoppingCart shoppingCart = new ShoppingCart();
            shoppingCart.setUserId(userId);
            shoppingCart.setImage(item.getImage());
            
            Long dishId = item.getDishId();
            Long setmealId = item.getSetmealId();
            
            if (dishId != null) {
                // 如果是菜品那就添加菜品的查询条件
                shoppingCart.setDishId(dishId);
            } else {
                // 添加到购物车的是套餐
                shoppingCart.setSetmealId(setmealId);
            }
            shoppingCart.setName(item.getName());
            shoppingCart.setDishFlavor(item.getDishFlavor());
            shoppingCart.setNumber(item.getNumber());
            shoppingCart.setAmount(item.getAmount());
            shoppingCart.setCreateTime(LocalDateTime.now());
            return shoppingCart;
        }).collect(Collectors.toList());

        // 将携带数据的购物车批量插入购物车表
        shoppingCartService.saveBatch(shoppingCartList);

        return Result.success("操作成功");
    }
}

实际测试

点击再来一单后,跳转购物车页面并且已经添加好相关菜品

地址功能补充(用户端)

我们将代码开发分为三部分

需求分析

功能解释:

我们的地址功能还缺少修改和删除操作

请求展示:

# 修改操作
请求 URL: //localhost:8080/addressBook
请求方法: PUT

# 删除操作
请求 URL: //localhost:8080/addressBook?ids=1583794867236589570
请求方法: DELETE

代码实现

代码展示:

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiuluo.reggie.common.BaseContext;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.AddressBook;
import com.qiuluo.reggie.service.AddressBookService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 地址簿管理
 */
@Slf4j
@RestController
@RequestMapping("/addressBook")
public class AddressBookController {

    @Autowired
    private AddressBookService addressBookService;

    /**
     * 额外添加功能:修改地址内容
     */
    @PutMapping
    public Result<String> update(@RequestBody AddressBook addressBook) {

        LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(AddressBook::getId,addressBook.getId());
        addressBookService.update(addressBook,queryWrapper);

        return Result.success("修改成功");
    }

    /**
     * 额外添加功能:删除地址内容
     * @param ids
     * @return
     */
    @DeleteMapping
    public Result<String> remove(Long ids){

        addressBookService.removeById(ids);

        return Result.success("修改成功");

    }
}

实际测试

分别进行修改和删除操作,操作成功即为功能开发成功

退出账户(用户端)

我们将代码开发分为三部分

需求分析

功能解释:

点击退出登录,退出账户回到登陆页面

请求展示:

# 退出账户
请求 URL: //localhost:8080/user/loginout
请求方法: POST

代码实现

代码展示:

package com.qiuluo.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiuluo.reggie.common.Result;
import com.qiuluo.reggie.domain.User;
import com.qiuluo.reggie.service.UserService;
import com.qiuluo.reggie.utils.SMSUtils;
import com.qiuluo.reggie.utils.ValidateCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.jws.soap.SOAPBinding;
import javax.servlet.http.HttpSession;
import java.util.Map;

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/loginout")
    public Result<String> loginOut(HttpSession session){

        // 去除Session即可
        session.removeAttribute("user");

        return Result.success("退出成功");
    }
}

实际测试

在用户页面退出后,回到登陆页面,查看Session信息为空即为功能开发成功

结束语

该篇内容到这里就结束了,希望能为你带来帮助~

附录

该文章属于学习内容,具体参考B站黑马程序员的Java项目实战《瑞吉外卖》

这里附上视频链接:业务开发Day1-01-本章内容介绍_哔哩哔哩_bilibili