0
点赞
收藏
分享

微信扫一扫

移动端菜品展示,购物车,下单

效果展示

移动端菜品展示,购物车,下单_数据

1. 导入用户地址簿相关功能代码  6-2

1.1 需求分析  6-2

移动端菜品展示,购物车,下单_数据_02

1.2 数据模型  6-2

用户的地址信息会存储在address_ book表,即地址簿表中。具体表结构如下:

移动端菜品展示,购物车,下单_数据_03

1.3 导入功能代码  6-2

功能代码清单:

●实体类AddressBook (直接从课程资料中导入即可)

●Mapper接口 AddressBookMapper

●业务层接口AddressBookService

●业务 层实现类AddressBookServicelmpl

●控制层AddressBookController ( 直接从课程资料中导入即可)

 地址簿实体类   AddressBook

package com.itheima.reggie.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 地址簿实体类  6-2
 */
@Data
public class AddressBook implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;


    //用户id
    private Long userId;


    //收货人
    private String consignee;


    //手机号
    private String phone;


    //性别 0 女 1 男
    private String sex;


    //省级区划编号
    private String provinceCode;


    //省级名称
    private String provinceName;


    //市级区划编号
    private String cityCode;


    //市级名称
    private String cityName;


    //区级区划编号
    private String districtCode;


    //区级名称
    private String districtName;


    //详细地址
    private String detail;


    //标签
    private String label;

    //是否默认 0 否 1是
    private Integer isDefault;

    //创建时间
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;


    //更新时间
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;


    //创建人
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;


    //修改人
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;


    //是否删除
    private Integer isDeleted;
}

地址簿 持久层接口AddressBookMapper

package com.itheima.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.reggie.entity.AddressBook;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

//地址簿 持久层接口  6-2
@Mapper
public interface AddressBookMapper extends BaseMapper<AddressBook> {

}

地址簿业务层接口 AddressBookService

package com.itheima.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.AddressBook;

//地址簿业务层接口  6-2
public interface AddressBookService extends IService<AddressBook> {

}

地址簿业务层接口 实现类AddressBookServiceImpl

package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.entity.AddressBook;
import com.itheima.reggie.mapper.AddressBookMapper;
import com.itheima.reggie.service.AddressBookService;
import org.springframework.stereotype.Service;


//地址簿业务层接口 实现类 6-2
@Service
public class AddressBookServiceImpl extends ServiceImpl<AddressBookMapper, AddressBook> implements AddressBookService {

}

地址簿管理  控制层AddressBookController

package com.itheima.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.itheima.reggie.common.BaseContext;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.AddressBook;
import com.itheima.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;

/**
 * 地址簿管理  控制层  6-2
 */
@Slf4j
@RestController
@RequestMapping("/addressBook")
public class AddressBookController {

    @Autowired
    private AddressBookService addressBookService;

    /**
     * 新增
     */
    @PostMapping
    public R<AddressBook> save(@RequestBody AddressBook addressBook) {
        addressBook.setUserId(BaseContext.getCurrentId());
        log.info("addressBook:{}", addressBook);
        addressBookService.save(addressBook);
        return R.success(addressBook);
    }

    /**
     * 设置默认地址
     */
    @PutMapping("default")
    public R<AddressBook> setDefault(@RequestBody AddressBook addressBook) {
        log.info("addressBook:{}", addressBook);
        LambdaUpdateWrapper<AddressBook> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(AddressBook::getUserId, BaseContext.getCurrentId());
        wrapper.set(AddressBook::getIsDefault, 0);
        //SQL:update address_book set is_default = 0 where user_id = ?
        addressBookService.update(wrapper);

        addressBook.setIsDefault(1);
        //SQL:update address_book set is_default = 1 where id = ?
        addressBookService.updateById(addressBook);
        return R.success(addressBook);
    }

    /**
     * 根据id查询地址
     */
    @GetMapping("/{id}")
    public R get(@PathVariable Long id) {
        AddressBook addressBook = addressBookService.getById(id);
        if (addressBook != null) {
            return R.success(addressBook);
        } else {
            return R.error("没有找到该对象");
        }
    }

    /**
     * 查询默认地址
     */
    @GetMapping("default")
    public R<AddressBook> getDefault() {
        LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AddressBook::getUserId, BaseContext.getCurrentId());
        queryWrapper.eq(AddressBook::getIsDefault, 1);

        //SQL:select * from address_book where user_id = ? and is_default = 1
        AddressBook addressBook = addressBookService.getOne(queryWrapper);

        if (null == addressBook) {
            return R.error("没有找到该对象");
        } else {
            return R.success(addressBook);
        }
    }

    /**
     * 查询指定用户的全部地址
     */
    @GetMapping("/list")
    public R<List<AddressBook>> list(AddressBook addressBook) {
        addressBook.setUserId(BaseContext.getCurrentId());
        log.info("addressBook:{}", addressBook);

        //条件构造器
        LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(null != addressBook.getUserId(), AddressBook::getUserId, addressBook.getUserId());
        queryWrapper.orderByDesc(AddressBook::getUpdateTime);

        //SQL:select * from address_book where user_id = ? order by update_time desc
        return R.success(addressBookService.list(queryWrapper));
    }
}

测试   6-2

新增成功

移动端菜品展示,购物车,下单_List_04

移动端菜品展示,购物车,下单_数据_05

设置默认地址成功

移动端菜品展示,购物车,下单_业务层_06

移动端菜品展示,购物车,下单_业务层_07

根据id查询地址

我们只要进入地址管理界面,就会自动根据用户id查询其下所有地址

移动端菜品展示,购物车,下单_List_08

1.4 拓展修改地址 自己实现

移动端菜品展示,购物车,下单_List_09

移动端菜品展示,购物车,下单_数据_10

AddressBookController

 //修改地址,自己实现
    @PutMapping
    public R<String> update(@RequestBody AddressBook addressBook){

        addressBookService.updateById(addressBook);

        return R.success("地址修改成功");
    }

修改成功

移动端菜品展示,购物车,下单_数据_11

2. 菜品展示  6-3

2.1 需求分析  6-3

移动端菜品展示,购物车,下单_数据_12

2.2 代码开发-梳理交互过程  6-4

在开发代码之前,需要梳理一下前端页面和服务端的交互过程:

1、页面(front/index.html)发送ajax请求,获取分类数据(菜品分类和套餐分类)

2、页面发送ajax请求,获取第一一个分类下的菜品或者套餐开发菜品展示功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。

注意:首页加载完成后,还发送了一次ajax请求用于加载购物车数据,此处可以将这次请求的地址暂时修改一下,从静态json文件获取数据,等后续开发购物车功能时再修改回来,如下:

移动端菜品展示,购物车,下单_业务层_13

2.3 展示菜品数据  功能开发  6-4

移动端菜品展示,购物车,下单_数据_14

移动端菜品展示,购物车,下单_业务层_15

移动端菜品展示,购物车,下单_数据_16

用户刚打开后,发送一个请求,用来获取菜品和套餐的分类信息,这个功能我们在之前已经开发了,但是为什么没有展示出来分类呢,因为页面紧接着有发送了另外一次请求加载购物车数据,但是我们还没实现此功能所以没有展示页面(因为前端写的是这两次请求必须同时成功,才可展示)

移动端菜品展示,购物车,下单_业务层_17

移动端菜品展示,购物车,下单_数据_18

所以我们为了不报错

在front下添加一个cartData.json的文件,应付一下这个请求

移动端菜品展示,购物车,下单_数据_19

移动端菜品展示,购物车,下单_数据_20

按ctrl,鼠标点击进入

移动端菜品展示,购物车,下单_List_21

修改以下

移动端菜品展示,购物车,下单_List_22

//获取购物车内商品的集合
function cartListApi(data) {
    return $axios({
        //'url': '/shoppingCart/list',
        'url': '/front/carData.json',
        'method': 'get',
        params:{...data}
    })
}

再次登录即可展示数据

(菜品展示功能我们之前已经开发了)

移动端菜品展示,购物车,下单_List_23

2.4 菜品展示改造  6-5

因为我们的菜品都设置了口味信息,但是前端并没有显示选择口味的按钮,只是有一个+号,是因为我们使用的返回类型是dish,其中并没有口味属性,所以使用dishDto作为返回值可以实现

移动端菜品展示,购物车,下单_业务层_24

菜品管理DishController

//根据菜品分类的id查询菜品改造  6-5
    @GetMapping("/list")
    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集合
        List<DishDto> dishDtoList = list.stream().map((item)->{
            DishDto dishDto = new DishDto();
            //将普通数据赋值进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);
            }

            //设置菜品口味
            Long id = item.getId();
            LambdaQueryWrapper<DishFlavor> dishFlavorLambdaQueryWrapper = new LambdaQueryWrapper<>();
            dishFlavorLambdaQueryWrapper.eq(DishFlavor::getDishId,id);
            List<DishFlavor> dishFlavorList = dishFlavorService.list(dishFlavorLambdaQueryWrapper);

            dishDto.setFlavors(dishFlavorList);

            return dishDto;

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

        return R.success(dishDtoList);
    }

测试成功

移动端菜品展示,购物车,下单_数据_25

移动端菜品展示,购物车,下单_List_26

2.5 展示套餐数据  6-6

移动端菜品展示,购物车,下单_List_27

套餐管理控制层SetmealController

/**
     * 根据条件查询套餐数据
     * @param setmeal
     * @return
     */
    @GetMapping("/list")
    public R<List<Setmeal>> list(Setmeal setmeal){
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());
        queryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);

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

        return R.success(list);
    }

测试

移动端菜品展示,购物车,下单_List_28

3. 购物车  6-7

3.1 需求分析  6-7

移动端菜品展示,购物车,下单_List_29

3.2 数据模型  6-7

购物车对应的数据表为shopping_cart表,具体表结构如下

移动端菜品展示,购物车,下单_业务层_30

购物车实体类 ShoppingCart

package com.itheima.reggie.entity;

import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 购物车实体类   6-7
 */
@Data
public class ShoppingCart implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;

    //名称
    private String name;

    //用户id
    private Long userId;

    //菜品id
    private Long dishId;

    //套餐id
    private Long setmealId;

    //口味
    private String dishFlavor;

    //数量
    private Integer number;

    //金额
    private BigDecimal amount;

    //图片
    private String image;

    private LocalDateTime createTime;
}

购物车持久层接口 ShoppingCartMapper

package com.itheima.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.reggie.entity.ShoppingCart;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

//购物车持久层接口  6-7
@Mapper
public interface ShoppingCartMapper extends BaseMapper<ShoppingCart> {

}

购物车业务层 接口ShoppingCartService

package com.itheima.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.ShoppingCart;

//购物车业务层 接口  6-7
public interface ShoppingCartService extends IService<ShoppingCart> {

}

购物车 业务层接口实现类ShoppingCartServiceImpl

package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.entity.ShoppingCart;
import com.itheima.reggie.mapper.ShoppingCartMapper;
import com.itheima.reggie.service.ShoppingCartService;
import org.springframework.stereotype.Service;

//购物车 业务层接口实现类  6-7
@Service
public class ShoppingCartServiceImpl extends ServiceImpl<ShoppingCartMapper, ShoppingCart> implements ShoppingCartService {

}

购物车控制层ShoppingCartController

package com.itheima.reggie.controller;


import com.itheima.reggie.service.ShoppingCartService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//购物车控制层
@Slf4j
@RestController
@RequestMapping("/shoppingCart")
public class ShoppingCartController {
    @Autowired
    private ShoppingCartService shoppingCartService;
    
}

3.3 代码开发-梳理交互过程  6-7

在开发代码之前,需要梳理一.下购物车操作时前端页面和服务端的交互过程:

1、点击加入购物车或者+按钮,页面发送ajax请求,请求服务端,将菜品或者套餐添加到购物车

2、点击购物车图标,页面发送ajax请求,请求服务端查询购物车中的菜品和套餐

3、点击清空购物车按钮,页面发送ajax请求,请求服务端来执行清空购物车操作

开发购物车功能,其实就是在服务端编写代码去处理前端页面发送的这3次请求即可。

3.4 加入购物车 功能开发  6-8

移动端菜品展示,购物车,下单_List_31

移动端菜品展示,购物车,下单_数据_32

购物车控制层ShoppingCartController

//加入购物车  6-8
    @PostMapping("/add")
    public R<ShoppingCart> add(@RequestBody ShoppingCart shoppingCart){
        log.info("购物车数据:{}",shoppingCart);

        //设置用户id
        //由debug调试和线圈传来的数据可知,前端并没有吧useId给我们,如果我们不设置userId的话
        //根本就不知道这个购物车是谁的
        //这个是从线程中取用户id
        Long currentId = BaseContext.getCurrentId();
        shoppingCart.setUserId(currentId);

        //查询当前添加菜品或者套餐是否已经存在购物车了
        Long dishId = shoppingCart.getDishId();
        //构造查询条件userId和菜品id或者套餐id可以查出唯一值
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId,currentId);

        if(dishId != null){
            //添加到购物车的是菜品
            queryWrapper.eq(ShoppingCart::getDishId,dishId);

        }else{
            //添加到购物车的是套餐
            queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId());
        }
        //查询
        //SQL:select * from shopping_cart where user_id = ? and dish_id/setmeal_id = ?
        ShoppingCart cartServiceOne = shoppingCartService.getOne(queryWrapper);

        //如果已经存在,就在原来数量基础上加一
        if(cartServiceOne != null){
            Integer number = cartServiceOne.getNumber();
            cartServiceOne.setNumber(number + 1);
            shoppingCartService.updateById(cartServiceOne);

        }else{//如果不存在,则添加到购物车,数量默认就是一
            shoppingCart.setNumber(1);
            shoppingCart.setCreateTime(LocalDateTime.now());
            shoppingCartService.save(shoppingCart);
            cartServiceOne = shoppingCart;
        }

        return R.success(cartServiceOne);
    }

测试添加成功

移动端菜品展示,购物车,下单_List_33

在添加相同的菜品

移动端菜品展示,购物车,下单_List_34

添加套餐成功

移动端菜品展示,购物车,下单_数据_35

移动端菜品展示,购物车,下单_业务层_36

3.5 查看购物车  6-9

把之前修改的也买你改回来

移动端菜品展示,购物车,下单_业务层_37

移动端菜品展示,购物车,下单_业务层_38

购物车控制层ShoppingCartController

/**
     * 查看购物车   6-9
     * @return
     */
    @GetMapping("/list")
    public R<List<ShoppingCart>> list(){
        log.info("查看购物车...");

        //构造查询条件,根据用户id来查
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
        queryWrapper.orderByAsc(ShoppingCart::getCreateTime);

        List<ShoppingCart> list = shoppingCartService.list(queryWrapper);

        return R.success(list);
    }

移动端菜品展示,购物车,下单_数据_39

3.6 清空购物车  6-9

移动端菜品展示,购物车,下单_List_40

购物车控制层ShoppingCartController

/**
     * 清空购物车  6-9
     * @return
     */
    @DeleteMapping("/clean")
    public R<String> clean(){
        //SQL:delete from shopping_cart where user_id = ?

        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());

        shoppingCartService.remove(queryWrapper);

        return R.success("清空购物车成功");
    }

移动端菜品展示,购物车,下单_业务层_41

移动端菜品展示,购物车,下单_List_42

3.7 减少购物车中的菜品数量  自己实现

移动端菜品展示,购物车,下单_List_43

移动端菜品展示,购物车,下单_List_44

购物车控制层ShoppingCartController

//减少购物车中的菜品或者套餐数量  自己实现
    @PostMapping("/sub")
    public R<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,dishId);
        }else {
            //是套餐
            queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId());
        }

        //取出菜品或者套餐的数据
        ShoppingCart cartServiceOne = shoppingCartService.getOne(queryWrapper);

        //查出当前菜品或者套餐的数量
        Integer number = cartServiceOne.getNumber();

        if(number==1){
            //菜品数量为1了,直接从购物车中删除
            shoppingCartService.remove(queryWrapper);
            cartServiceOne.setNumber(0);
            return R.success(cartServiceOne);
        }else {
            cartServiceOne.setNumber(number-1);
            shoppingCartService.updateById(cartServiceOne);
        }

        return R.success(cartServiceOne);//这个返回是给前端页面做展示的,不是给购物车的而购物车会自己刷新
    }

测试成功

移动端菜品展示,购物车,下单_List_45

移动端菜品展示,购物车,下单_List_46

4. 用户下单  6-10

4.1 需求分析  6-10

移动端菜品展示,购物车,下单_List_47

4.2 数据模型  6-10

用户下单业务对应的数据表为orders表和order_ _detail表 :

●orders: 订单表

●order_ detail: 订单明细表

移动端菜品展示,购物车,下单_数据_48

移动端菜品展示,购物车,下单_数据_49

4.3 代码开发-梳理交互过程  6-11

在开发代码之前,需要梳理一下用户下单操作时前端页面和服务端的交互过程:

1、在购物车中点击去结算按钮, 页面跳转到订单确认页面

2、在订单确认页面,发送ajax请求,请求服务端获取当前登录用户的默认地址

3、在订单确认页面,发送ajax请求,请求服务端获取当前登录用户的购物车数据

4、在订单确认页面点击去支付按钮, 发送ajax请求,请求服务端完成 下单操作

开发用户下单功能,其实就是在服务端编写代码去处理前端页面发送的请求即可。

移动端菜品展示,购物车,下单_List_50

移动端菜品展示,购物车,下单_List_51

4.4 数据准备  6-11

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

●实体类Orders. OrderDetail ( 直接从课程资料中导入即可)

●Mapper接口 OrderMapper、OrderDetailMapper

●业务层接口OrderService、OrderDetailService

●业务层实现类OrderServicelmpl、OrderDetailServicelmpl

●控制层OrderController. OrderDetailController

 订单实体类 Orders

package com.itheima.reggie.entity;

import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 订单实体类  6-11
 */
@Data
public class Orders implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;

    //订单号
    private String number;

    //订单状态 1待付款,2待派送,3已派送,4已完成,5已取消
    private Integer status;


    //下单用户id
    private Long userId;

    //地址id
    private Long addressBookId;


    //下单时间
    private LocalDateTime orderTime;


    //结账时间
    private LocalDateTime checkoutTime;


    //支付方式 1微信,2支付宝
    private Integer payMethod;


    //实收金额
    private BigDecimal amount;

    //备注
    private String remark;

    //用户名
    private String userName;

    //手机号
    private String phone;

    //地址
    private String address;

    //收货人
    private String consignee;
}

订单明细实体类OrderDetail

package com.itheima.reggie.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;

/**
 * 订单明细实体类
 */
@Data
public class OrderDetail implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;

    //名称
    private String name;

    //订单id
    private Long orderId;


    //菜品id
    private Long dishId;


    //套餐id
    private Long setmealId;


    //口味
    private String dishFlavor;


    //数量
    private Integer number;

    //金额
    private BigDecimal amount;

    //图片
    private String image;
}

订单持久层接口OrderMapper

package com.itheima.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.reggie.entity.Orders;
import org.apache.ibatis.annotations.Mapper;

//订单持久层接口  6-11
@Mapper
public interface OrderMapper extends BaseMapper<Orders> {

}

订单明细持久层接口OrderDetailMapper

package com.itheima.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.reggie.entity.OrderDetail;
import org.apache.ibatis.annotations.Mapper;

//订单明细持久层接口  6-11
@Mapper
public interface OrderDetailMapper extends BaseMapper<OrderDetail> {

}

订单业务层接口OrderService

package com.itheima.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.Orders;

//订单业务层接口  6-11
public interface OrderService extends IService<Orders> {

}

订单明细业务层接口OrderDetailService

package com.itheima.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.OrderDetail;

//订单明细业务层接口  6-11
public interface OrderDetailService extends IService<OrderDetail> {

}

订单业务层接口实现类OrderServiceImpl

package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.mapper.OrderMapper;
import com.itheima.reggie.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;


//订单业务层接口实现类  6-11
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {

}

订单业务层接口实现类OrderServiceImpl

package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.mapper.OrderMapper;
import com.itheima.reggie.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;


//订单业务层接口实现类  6-11
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {

}

订单明细业务层接口实现类OrderDetailServiceImpl

package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.entity.OrderDetail;
import com.itheima.reggie.mapper.OrderDetailMapper;
import com.itheima.reggie.service.OrderDetailService;
import org.springframework.stereotype.Service;

//订单明细业务层接口实现类  6-11
@Service
public class OrderDetailServiceImpl extends ServiceImpl<OrderDetailMapper, OrderDetail> implements OrderDetailService {

}

订单控制层OrderController

package com.itheima.reggie.controller;

import com.itheima.reggie.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//订单控制层  6-11
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;
    
}

订单明细控制层OrderDetailController

package com.itheima.reggie.controller;

import com.itheima.reggie.service.OrderDetailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//订单明细控制层  6-11
@Slf4j
@RestController
@RequestMapping("/orderDetail")
public class OrderDetailController {
    @Autowired
    private OrderDetailService orderDetailService;
}

4.4 用户下单功能开发  6-12

移动端菜品展示,购物车,下单_List_52

移动端菜品展示,购物车,下单_数据_53

订单业务层接口OrderService

//用户下单  6-12
    public void submit(Orders orders);

订单业务层接口实现类OrderServiceImpl

package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.common.BaseContext;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.mapper.OrderMapper;
import com.itheima.reggie.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;


//订单业务层接口实现类  6-11
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private UserService userService;

    @Autowired
    private AddressBookService addressBookService;

    @Autowired
    private OrderDetailService orderDetailService;

    //用户下单  6-12  6-13  6-14
    @Override
    @Transactional
    public void submit(Orders orders) {
        //获得当前用户id
        Long userId = BaseContext.getCurrentId();

        //查询当前用户的购物车数据
        //根据用户id查
        LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ShoppingCart::getUserId,userId);
        List<ShoppingCart> shoppingCarts = shoppingCartService.list(wrapper);

        if(shoppingCarts == null || shoppingCarts.size() == 0){
            throw new CustomException("购物车为空,不能下单");
        }

        //查询用户数据
        User user = userService.getById(userId);

        //查询地址数据
        Long addressBookId = orders.getAddressBookId();
        AddressBook addressBook = addressBookService.getById(addressBookId);
        if(addressBook == null){
            throw new CustomException("用户地址信息有误,不能下单");
        }

        //以上将订单表所需数据都准备好了,下面直接将上述数据封装进订单表数据库即可

        //生成订单号  6-14
        long orderId = IdWorker.getId();

        //遍历购物车数据,计算总金额和封装订单明细表数据
        AtomicInteger amount = new AtomicInteger(0);//用来计算金额,他是一个原子的操作,在多线程也可以保证数据准确
        List<OrderDetail> orderDetails = shoppingCarts.stream().map((item)->{
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);//订单id
            orderDetail.setNumber(item.getNumber());//菜品或者套餐数量
            orderDetail.setDishFlavor(item.getDishFlavor());//菜品口味
            orderDetail.setDishId(item.getDishId());//菜品id
            orderDetail.setSetmealId(item.getSetmealId());//套餐id
            orderDetail.setName(item.getName());//菜品或者套餐名字
            orderDetail.setImage(item.getImage());//菜品或者套餐图片
            orderDetail.setAmount(item.getAmount());//菜品或者套餐单份价格
            //计算菜品或者套餐的总金额
            amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());
            return orderDetail;
        }).collect(Collectors.toList());

        //向订单表插入数据  6-14
        orders.setId(orderId);//订单id
        orders.setOrderTime(LocalDateTime.now());//生成订单时间
        orders.setCheckoutTime(LocalDateTime.now());//结账时间
        orders.setStatus(2);//2代表带派送
        orders.setAmount(new BigDecimal(amount.get()));//总金额
        orders.setUserId(userId);//用户id
        orders.setNumber(String.valueOf(orderId));//订单编号
        orders.setUserName(user.getName());//下单用户名字
        orders.setConsignee(addressBook.getConsignee());//收货人名字
        orders.setPhone(addressBook.getPhone());//收货人手机号
        //设置收货人详细信息
        orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
                + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));

        //向订单表插入一条数据
        this.save(orders);

        //向订单明细表插入插入数据
        orderDetailService.saveBatch(orderDetails);

        //清空购物车
        shoppingCartService.remove(wrapper);

    }
}

订单控制层OrderController

/**
     * 用户下单   6-12
     * @param orders
     * @return
     */
    @PostMapping("/submit")
    public R<String> submit(@RequestBody Orders orders){
        log.info("订单数据:{}",orders);
        orderService.submit(orders);
        return R.success("下单成功");
    }

测试成功

移动端菜品展示,购物车,下单_List_54

移动端菜品展示,购物车,下单_数据_55

移动端菜品展示,购物车,下单_业务层_56

5. 服务端订单明细   自己实现

移动端菜品展示,购物车,下单_List_57

移动端菜品展示,购物车,下单_数据_58

订单控制层OrderController

//服务端订单明细 分页查询  自己实现
    @GetMapping("/page")
    public R<Page> page(int page,int pageSize,String number){

        //构造分页构造器
        Page<Orders> pageInfo = new Page<>();

        //构造查询条件
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        //构造订单号进行模糊查询
        queryWrapper.eq(number!=null,Orders::getNumber,number);

        //添加排序条件,根据更新时间降序排列
        queryWrapper.orderByDesc(Orders::getOrderTime);

        orderService.page(pageInfo,queryWrapper);

        return R.success(pageInfo);

    }

测试成功

移动端菜品展示,购物车,下单_List_59

6. 移动端 显示订单明细  自己实现

移动端菜品展示,购物车,下单_业务层_60

移动端菜品展示,购物车,下单_业务层_61

订单控制层OrderController

有bug

//移动端订单明细 分页查询  自己实现,由bug
    @GetMapping("/userPage")
    public R<Page> userPage(int page,int pageSize){
        //构造分页构造器
        Page<Orders> pageInfo = new Page<>();

        //构造查询条件
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        //构造用户id进行查询
        queryWrapper.eq(Orders::getUserId, BaseContext.getCurrentId());

        //添加排序条件,根据更新时间降序排列
        queryWrapper.orderByDesc(Orders::getOrderTime);

        orderService.page(pageInfo,queryWrapper);

        return R.success(pageInfo);
    }

7. 移动端客户退出登录  自己实现

移动端菜品展示,购物车,下单_数据_62

UserController

//移动端客户退出登录  自己实现
    @PostMapping("/loginout")
    public R<String> logout(HttpServletRequest request){
        //1、清理Session中的用户id
        request.getSession().removeAttribute("user");
        //2、返回结果
        return R.success("退出登录成功");
    }

移动端菜品展示,购物车,下单_List_63

移动端菜品展示,购物车,下单_数据_64

至此项目基础部分已经完成,后面开始对项目进行优化

举报

相关推荐

0 条评论