瑞吉外卖day5
套餐管理业务
新增套餐
需求分析
套餐救赎菜品的集合,后台管理系统中可以管理套餐信息,通过新增套餐功能来添加一个新的套餐,在添加套餐时需要选择当前套餐所属的套餐分类和包含的菜品,并且需要上传套餐对应的图片,在移动端会按照套餐分类来展示对应的套餐
数据模型
所以在新增套餐时,涉及到两个表:
新增套餐,其实就是将新增页面录入的套餐信息插入到setmeal表,还需要向setmeal dish表插入套餐和菜品关联数据。
setmea l套餐表
setmeal dish 套餐菜品关系表
代码开发-准备工作
在开发业务功能前,先将需要用到的类和接口基本结构创建好:
实体类SetmealDish,DTO SetmealDto
Mapper接口 SetmealDishMapper
业务层接口 SetmealDishService
业务层实现类 SetmealDishServicelmpl
控制层 SetmealController
代码开发-梳理交互
1、页面(backend/page/combo/add.html)发送ajax请求,请求服务端获取套餐分类数据并展示到下拉框中
2、页面发送ajax请求,请求服务端获取菜品分类数据并展示到添加菜品窗口中
3、页面发送ajax请求,请求服务端,根据菜品分类查询对应的菜品数据并展示到添加菜品窗口中
/** * 根据菜品分类查询菜品 * @param dish * @return */ @GetMapping("/list") public R<List<Dish>> listR(Dish dish){ //添加查询条件 LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId()); //查询状态为起售的菜品 queryWrapper.eq(Dish::getStatus,1); queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime); List<Dish> list = dishService.list(queryWrapper); return R.success(list); }
4、页面发送请求进行图片上传,请求服务端将图片保存到服务器
5、页面发送请求进行图片下载,将上传的图片进行回显
6、点击保存按钮,发送ajax请求,将套餐相关数据以json形式提交到服务端
/** * 新增套餐分类 * @param setmealDto * @return */ @PostMapping public R<String> save(@RequestBody SetmealDto setmealDto){ setmealService.saveWithDish(setmealDto); return R.success("新增套餐分类成功"); }
/** * 新增套餐,同时保存套餐和菜品之间的关联关系 * @param setmealDto */ @Override public void saveWithDish(SetmealDto setmealDto) { this.save(setmealDto); List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes(); setmealDishes= setmealDishes.stream().map((item)->{ item.setSetmealId(setmealDto.getId()); return item; }).collect(Collectors.toList()); setmealDishService.saveBatch(setmealDishes); }
套餐信息分页查询
需求分析
系统中的套餐数据很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般系统中都会以分页的方式来展示列表数据。
代码开发-梳理交互过程
1、页面(backend/page/combo/list.html)发送ajax请求,将分页查询参数(page、pageSize、name)提交到服务端,获取分页数据
2、页面发送请求,请求服务端进行图片下载,用于页面图片展示
/** * 套餐分页查询 * @param page * @param pageSize * @param name * @return */ @GetMapping("/page") public R<Page> page(int page,int pageSize,String name){ Page<Setmeal> pageInfo = new Page(page,pageSize); Page<SetmealDto> dtoPage = new Page<>(); LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.like(name!=null,Setmeal::getName,name); queryWrapper.orderByDesc(Setmeal::getUpdateTime); setmealService.page(pageInfo,queryWrapper); BeanUtils.copyProperties(pageInfo,dtoPage,"records"); List<Setmeal> records = pageInfo.getRecords(); List<SetmealDto> list = records.stream().map((item)->{ SetmealDto setmealDto = new SetmealDto(); BeanUtils.copyProperties(item,setmealDto); Long categoryId=item.getCategoryId(); Category category= categoryService.getById(categoryId); if (category!=null){ String categoryName =category.getName(); setmealDto.setCategoryName(categoryName); } return setmealDto; }).collect(Collectors.toList()); dtoPage.setRecords(list); return R.success(dtoPage); }
删除套餐
需求分析
在套餐管理列表页面点击删除按钮,可以删除对应的套餐信息。也可以通过复选框选择多个套餐,点击批量删除按钮一次删除多个套餐。注意,对于状态为售卖中的套餐不能删除,需要先停售,然后才能删除。
代码开发-梳理交互过程
1、删除单个套餐时,页面发送ajax请求,根据套餐id删除对应套餐
2、删除多个套餐时,页面发送ajax请求,根据提交的多个套餐id删除对应套餐
开发删除套餐功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。
观察删除单个套餐和批量删除套餐的请求信息可以发现,两种请求的地址和请求方式都是相同的
不同的则是
传递的id个数,所以在服务端可以提供一个方法来统一处理。
@DeleteMapping public R<String> delete(@RequestParam List<Long> ids){ log.info("要删除的id为{}",ids); setmealService.removeWithDish(ids); return R.success("删除成功"); } }
删除套餐时,不仅要将套餐表中的相关数据进行删除,同时还要将套餐菜品关联表中的数据一并删除
/** * 删除套餐,同时删除套餐菜品关联表中的信息 * @param ids */ @Override public void removeWithDish(List<Long> ids) { LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(Setmeal::getId,ids); queryWrapper.eq(Setmeal::getStatus,1); int count = this.count(queryWrapper); if (count>0){ throw new CustomException("套餐正在售卖中,不能停售"); } this.removeByIds(ids); LambdaQueryWrapper<SetmealDish> queryWrapper1 = new LambdaQueryWrapper<>(); queryWrapper1.in(SetmealDish::getSetmealId,ids); setmealDishService.remove(queryWrapper1); }
手机验证码登录
代码开发
1.导入Maven坐标
2.调用阿里云短信服务API
需求分析
为了方便用户登录,移动端通常都会提供通过手机验证码登录的功能
手机验证码登录的优点:
方便快捷,无需注册,直接登录
使用短信验证码作为登录凭证,无需记忆密码安全
登录流程:
输入手机号>获取验证码>输入验证码>点击登录>登录成功
注意:通过手机验证码登录,手机号是区分不同用户的标识。
代码开发-梳理交互过程
在开发代码之前,需要梳理一下登录时前端页面和服务端的交互过程:
1、在登录页面(front/page/login.html)输入手机号,点击【获取验证码】按钮,页面发送ajax请求,在服务端调用短信服务API给指定手机号发送验证码短信
2、在登录页面输入验证码,点击【登录】按钮,发送ajax请求,在服务端处理登录请求
开发手机验证码登录功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。
代码开发
使用阿里云短信服务
@PostMapping("/sendMsg") public R<String> sendMsg(@RequestBody User user, HttpSession httpSession){ String phone = user.getPhone(); if (StringUtils.isNotEmpty(phone)){ String code = ValidateCodeUtils.generateValidateCode(4).toString(); log.info(code); SMSUtils.sendMessage("屁屁外卖","SMS_460880120",phone,code); httpSession.setAttribute(phone,code); return R.success("验证码发送成功"); } return R.error("验证码发送失败"); }
登录接口
@PostMapping("/login") public R<User> login(@RequestBody Map map,HttpSession httpSession){ log.info("user={}",map); //获取手机号 String phone = map.get("phone").toString(); //获取验证码 String code = map.get("code").toString(); //从Session中获取保存的验证码 Object codeInSession = httpSession.getAttribute(phone); if (codeInSession!=null&&codeInSession.equals(code)){ //如果比对成功,说明登陆成功 LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(User::getPhone,phone); User user = userService.getOne(queryWrapper); if (user==null){ user = new User(); user.setPhone(phone); user.setStatus(1); userService.save(user); } httpSession.setAttribute("user",user.getId()); return R.success(user); } return R.error("登陆失败"); }