当前位置:网站首页>【项目】小帽外卖(五)
【项目】小帽外卖(五)
2022-04-21 06:59:00 【柠檬小帽】
小帽外卖
第五章 套餐管理业务开发
一、新增套餐
1. 需求分析
- 套餐就是菜品的集合。
- 后台系统中可以管理套餐信息,通过新增套餐功能来添加一个新的套餐,在添加套餐时需要选择当前套餐所属的套餐分类和包含的菜品,并且需要上传套餐对应的图片,在移动端会按照套餐分类来展示对应的套餐。

2. 数据模型
- 新增套餐,其实就是将新增页面录入的套餐信息插入到setmeal表,还需要向setmeal_dish表插入套餐和菜品关联数据。
- 所以在新增套餐时,涉及到两个表:
- setmeal 套餐表
- setmeal_dish 套餐菜品关系表
- 套餐表setmeal:

- 套餐菜品关系表setmeal_dish:

3. 代码开发
3.1 准备工作
- 在开发业务功能前,先将需要用到的类和接口基本结构创建好:
- 实体类 SetmealDish
- DTO SetmealDto
- Mapper接口 SetmealDishMapper
- 业务层接口 SetmealDishService
- 业务层实现类 SetmealDishServiceImpl
- 控制层 SetmealController
3.2 梳理交互过程
- 在开发代码之前,需要梳理一下新增套餐时前端页面和服务端的交互过程:
- 页面(backend/page/combo/add.html)发送ajax请求,请求服务端获取套餐分类数据并展示到下拉框中
- 页面发送ajax请求,请求服务端获取菜品分类数据并展示到添加菜品窗口中
- 页面发送ajax请求,请求服务端,根据菜品分类查询对应的菜品数据并展示到添加菜品窗口中
- 页面发送请求进行图片上传,请求服务端将图片保存到服务器
- 页面发送请求进行图片下载,将上传的图片进行回显
- 点击保存按钮,发送ajax请求,将套餐相关数据以json形式提交到服务端
- 开发新增套餐功能,其实就是在服务端编写代码去处理前端页面发送的这6次请求即可。
@RestController
@RequestMapping("/dish")
@Slf4j
public class DishController {
@Autowired
private DishService dishService;
/** * 根据条件查询对应的菜品数据 * @param dish * @return */
@GetMapping("/list")
public R<List<Dish>> 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);
return R.success(list);
}
}
@RestController
@RequestMapping("/setmeal")
@Slf4j
public class SetmealController {
@Autowired
private SetmealService setmealService;
@Autowired
private SetmealDishService setmealDishService;
/** * 新增套餐 * @param setmealDto * @return */
@PostMapping
public R<String> save(@RequestBody SetmealDto setmealDto) {
log.info("套餐信息:{}", setmealDto);
setmealService.saveWithDish(setmealDto);
return R.success("新增套餐成功");
}
}
public interface SetmealService extends IService<Setmeal> {
/** * 新增套餐,同时需要保存套餐和菜品的关联关系 * @param setmealDto */
public void saveWithDish(SetmealDto setmealDto);
}
@Service
@Slf4j
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
@Autowired
private SetmealDishService setmealDishService;
/** * 新增套餐,同时需要保存套餐和菜品的关联关系 * @param setmealDto */
@Override
@Transactional
public void saveWithDish(SetmealDto setmealDto) {
// 保存套餐的基本信息,操作setmeal,执行insert操作
this.save(setmealDto);
List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
setmealDishes = setmealDishes.stream().map((item) -> {
item.setSetmealId(setmealDto.getId());
return item;
}).collect(Collectors.toList());
// 保存套餐和菜品的关联信息,操作setmeal_dish,执行insert操作
setmealDishService.saveBatch(setmealDishes);
}
}
二、 套餐信息分页查询
1. 需求分析
- 系统中的套餐数据很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。

2. 代码开发
- 梳理交互过程
- 在开发代码之前,需要梳理一下套餐分页查询时前端页面和服务端的交互过程:
- 页面(backend/page/combo/list.html)发送ajax请求,将分页查询参数(page、pageSize、name)提交到服务端,获取分页数据
- 页面发送请求,请求服务端进行图片下载,用于页面图片展示
- 开发套餐信息分页查询功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。
- 在开发代码之前,需要梳理一下套餐分页查询时前端页面和服务端的交互过程:
@RestController
@RequestMapping("/setmeal")
@Slf4j
public class SetmealController {
@Autowired
private SetmealService setmealService;
@Autowired
private CategoryService categoryService;
@Autowired
private SetmealDishService setmealDishService;
@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<>();
// 添加查询条件,根据name进行like模糊查询
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);
// 分类id
Long categoryId = item.getCategoryId();
// 根据分类id查询分类对象
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. 需求分析
- 在套餐管理列表页面点击删除按钮,可以删除对应的套餐信息。也可以通过复选框选择多个套餐,点击批量删除按钮一次删除多个套餐。注意,对于状态为售卖中的套餐不能删除,需要先停售,然后才能删除。
2. 梳理交互过程
- 在开发代码之前,需要梳理一下删除套餐时前端页面和服务端的交互过程:
- 删除单个套餐时,页面发送ajax请求,根据套餐id删除对应套餐

- 删除多个套餐时,页面发送ajax请求,根据提交的多个套餐id删除对应套餐

- 删除单个套餐时,页面发送ajax请求,根据套餐id删除对应套餐
- 开发删除套餐功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。
- 观察删除单个套餐和批量删除套餐的请求信息可以发现,两种请求的地址和请求方式都是相同的,不同的则是传递的id个数,所以在服务端可以提供一个方法来统一处理。
@RestController
@RequestMapping("/setmeal")
@Slf4j
public class SetmealController {
@Autowired
private SetmealService setmealService;
@Autowired
private CategoryService categoryService;
@Autowired
private SetmealDishService setmealDishService;
/** * 删除套餐 * @param ids * @return */
@DeleteMapping
public R<String> delete(@RequestParam List<Long> ids) {
log.info("ids:{}", ids);
setmealService.removeWithDish(ids);
return R.success("套餐数据删除成功");
}
}
public interface SetmealService extends IService<Setmeal> {
/** * 删除套餐,同时需要删除套餐和菜品的关联数据 * @param ids */
public void removeWithDish(List<Long> ids);
}
@Service
@Slf4j
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
@Autowired
private SetmealDishService setmealDishService;
/** * 删除套餐,同时需要删除套餐和菜品的关联数据 * @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("套餐正在售卖中,不能删除");
}
// 如果可以删除,先删除套餐表中的数据 -- setmeal
this.removeByIds(ids);
LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.in(SetmealDish::getSetmealId,ids);
// 删除关系表中的数据 -- setmeal_dish
setmealDishService.remove(lambdaQueryWrapper);
}
}
版权声明
本文为[柠檬小帽]所创,转载请带上原文链接,感谢
https://blog.csdn.net/sgsgkxkx/article/details/124301419
边栏推荐
猜你喜欢

蓝牙开源协议栈BTstack之1.0 BTstack简介

kubesphere3.0忘记admin的密码

动态规划--LC474.一和零

Introduction to zephyr 1.0 of Internet of things operating system zephyr (Introduction)

结合实际聊聊防反接电路(防反接电路总结)

从零开始自制实现WebServer(十五)---- 日志库部分完结啦 实用小件DOUBLE-BUFFERING优化异步写入性能

ECS uses FRP to map Apache on the local (win10 / win11) intranet to the extranet

2022年危险化学品生产单位安全生产管理人员考试模拟100题模拟考试平台操作

Hackmyvm综合靶机 | Driftingblues-9(完结)

STM32系统和自定义bootloader的实现和应用
随机推荐
Advanced C language pointer (1. First and second order pointers)
SQL command of Oracle management
从零开始学习C语言日记——DAY27扫雷
PostgreSQL 15 will soon support merge statements in the SQL standard
Yolov5 5.0调用本地摄像头
Build openwrt file system for i.mx6q development board
GoLang学习资源清单
2022年危险化学品生产单位安全生产管理人员考试模拟100题模拟考试平台操作
[question 31] create two identical pets
Leetcode topic -- 120 Minimum length sum of triangles, simple DP
Neptune w800点灯(中断)工程详解
Project storage log
Signals
torch中permute()函数用法补充内容(矩阵维度变化详细过程)
Introduction to threads -- thread class -- several ways to start threads
Environment Variables
The fifth stop is the hometown of Confucius and Mencius ------- the shortest path to the maze
注解功能补充
EF de duplication operation
【知行】浅谈Switch与If