学成在线项目笔记第三期
删除课程计划
需求分析
接口定义
删除课程计划的接口示例如下:
1 2 3 4 5 6 7
| Request URL: /content/teachplan/246 Request Method: DELETE
如果失败: {"errCode":"120409","errMessage":"课程计划信息还有子级信息,无法操作"}
如果成功:状态码200,不返回信息
|
接口开发
model
model层直接用之前开发的DTO即可,无需添加新类
api-接口定义
在课程计划teachplan的controller中添加接口
1 2 3 4
| @DeleteMapping("/teachplan/{id}") public List<TeachplanDto> deleteTeachplan(@PathVariable Long id){ return teachplanService.deleteTeachplan(id); }
|
service-接口开发
创建service接口
在teachplan的service中创建接口:
1 2 3 4 5 6 7
|
public List<TeachplanDto> deleteTeachplan(Long id);
|
创建service实现类impl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| @Transactional @Override public List<TeachplanDto> deleteTeachplan(Long id) { Teachplan teachplan = teachplanMapper.selectById(id); Long courseId = teachplan.getCourseId(); if (teachplan == null) { throw new XueChengException("无法找到该章节"); }
LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Teachplan::getParentid, id); Integer count = teachplanMapper.selectCount(queryWrapper); if (count > 0) { throw new XueChengException("存在子章节,无法删除该章节"); }
Long teachplanId = teachplan.getId(); LambdaQueryWrapper<TeachplanMedia> query = new LambdaQueryWrapper<>(); query.eq(TeachplanMedia::getTeachplanId, teachplanId); Integer mediaCount = teachplanMediaMapper.selectCount(query); if (mediaCount > 0) { teachplanMediaMapper.delete(query); } teachplanMapper.deleteById(teachplanId); return teachplanMapper.selectTreeNodes(courseId); }
|
接口测试
首先使用httpclient测试
1 2
| ### 删除课程计划 DELETE {{content_host}}/content/teachplan/43
|
分以下情况测试:
删除有子课程计划的计划。
删除没有子课程计划的计划。
课程计划排序
需求分析
课程计划新增后默认排在同级别最后,课程计划排序功能是可以灵活调整课程计划的显示顺序
接口定义
向下移动
1 2 3
| Request URL: http://localhost:8601/api/content/teachplan/movedown/43 Request Method: POST 43为课程计划id
|
向上移动
1 2 3
| Request URL: http://localhost:8601/api/content/teachplan/moveup/43 Request Method: POST 43为课程计划id
|
接口开发
model
没有新的配置,略
api-接口定义
在课程计划teachplan的controller中添加接口
1 2 3 4 5 6 7 8 9
| @PostMapping("/teachplan/moveup/{id}") public void moveup(@PathVariable Long id){ teachplanService.moveup(id); }
@PostMapping("/teachplan/movedown/{id}") public void movedown(@PathVariable Long id){ teachplanService.movedown(id); }
|
service-接口开发
创建service接口
在teachplan的service中创建接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public void moveup(Long id);
public void movedown(Long id);
|
创建service实现类impl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| @Override public void moveup(Long id) { Teachplan teachplan = teachplanMapper.selectById(id); Long parentid = teachplan.getParentid(); Integer targetOrderby = teachplan.getOrderby(); if (targetOrderby == 1) { throw new XueChengException("已经是第一个了,无法继续上移"); } LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Teachplan::getParentid, parentid); queryWrapper.lt(Teachplan::getOrderby, targetOrderby); Integer count = teachplanMapper.selectCount(queryWrapper); if (count >= 1) { queryWrapper.eq(Teachplan::getOrderby, targetOrderby - 1); Teachplan preTeachplan = teachplanMapper.selectOne(queryWrapper); preTeachplan.setOrderby(preTeachplan.getOrderby() + 1); teachplanMapper.updateById(preTeachplan); teachplan.setOrderby(targetOrderby - 1); } teachplanMapper.updateById(teachplan); }
@Override public void movedown(Long id) { Teachplan teachplan = teachplanMapper.selectById(id); Long parentid = teachplan.getParentid(); Integer targetOrderby = teachplan.getOrderby(); LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Teachplan::getParentid, parentid); queryWrapper.gt(Teachplan::getOrderby, targetOrderby); Integer count = teachplanMapper.selectCount(queryWrapper); if (count == 0) { throw new XueChengException("已经是最后一个了,无法继续下移"); } else { queryWrapper.eq(Teachplan::getOrderby, targetOrderby + 1); Teachplan preTeachplan = teachplanMapper.selectOne(queryWrapper); preTeachplan.setOrderby(preTeachplan.getOrderby() - 1); teachplanMapper.updateById(preTeachplan); teachplan.setOrderby(targetOrderby + 1); } teachplanMapper.updateById(teachplan); }
|
接口测试
这个功能直接前后端联调,这个可能立即看到 效果。
向上移动测试
先找一个上边有课程计划的进行测试,向上移动后两个交换顺序。
再找最上边的课程计划向上移动,应该没有反映才对,因为已经在最上边了。
向下移动测试
先找一个下边有课程计划的进行测试,向下移动后两个交换顺序。
再找最下边的课程计划向下移动,应该没有反映才对,因为已经在最下边了。
师资管理
完成以实战内容需要将课程资料下的course-add-step3-teacher.vue文件 覆盖 project-xczx2-portal-
vue-ts\src\module-organization\pages\course-manage\course-add-step3-teacher.vue
需求分析
注意:只允许向机构自己的课程中添加老师、删除老师。
机构id统一使用:1232141425L
接口定义
查询教师接口请求示例
1 2 3 4 5 6
| get /courseTeacher/list/75 75为课程id,请求参数为课程id
响应结果 [{"id":23,"courseId":75,"teacherName":"张老师","position":"讲师","introduction":"张老师教师简介张老师教师简介张老师教师简介张老师教师简 介","photograph":null,"createDate":null}]
|
添加教师请求示例
1 2 3 4 5 6 7 8 9 10
| post /courseTeacher 请求参数: { "courseId": 75, "teacherName": "王老师", "position": "教师职位", "introduction": "教师简介" } 响应结果: {"id":24,"courseId":75,"teacherName":"王老师","position":"教师职位","introduction":"教师简介","photograph":null,"createDate":null}
|
修改教师
1 2 3 4 5 6 7 8 9 10 11 12 13
| post /courseTeacher 请求参数: { "id": 24, "courseId": 75, "teacherName": "王老师", "position": "教师职位", "introduction": "教师简介", "photograph": null, "createDate": null } 响应: {"id":24,"courseId":75,"teacherName":"王老师","position":"教师职位","introduction":"教师简介","photograph":null,"createDate":null}
|
删除教师
1 2 3 4 5 6
| delete /ourseTeacher/course/75/26 75:课程id 26:教师id,即course_teacher表的主键
请求参数:课程id、教师id 响应:状态码200,不返回信息
|
接口开发
师资管理功能开发全部都在 content 工程中进行
model
直接使用mybatis生成的po类即可,略
api-接口定义
根据接口定义,在 content-api中创建新的controller,创建接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| package com.xuecheng.contentApi.controller;
import com.xuecheng.contentModel.po.CourseTeacher; import com.xuecheng.contentService.service.CourseTeacherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController public class CourseTeacherController {
@Autowired CourseTeacherService courseTeacherService;
@GetMapping("/courseTeacher/list/{courseId}") public List<CourseTeacher> selectCourseTeacher(@PathVariable Long courseId){ return courseTeacherService.getCourseTeacherInfo(courseId); }
@PostMapping("/courseTeacher") public CourseTeacher saveCourseTeacher(@RequestBody @Validated CourseTeacher teacher){ Long companyId = 1232141425L; return courseTeacherService.saveCourseTeacher(teacher); }
@DeleteMapping("/courseTeacher/course/{courseId}/{id}") public void deleteCourseTeacher(@PathVariable Long courseId, @PathVariable Long id){ courseTeacherService.deleteCourseTeacher(courseId, id); } }
|
service-接口开发
创建service接口
在courseteacher的service中创建接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package com.xuecheng.contentService.service;
import com.xuecheng.contentModel.po.CourseTeacher;
import java.util.List;
public interface CourseTeacherService {
public List<CourseTeacher> getCourseTeacherInfo(Long courseId);
public CourseTeacher saveCourseTeacher(CourseTeacher teacher);
public void deleteCourseTeacher(Long courseId, Long id); }
|
创建service实现类impl
实现 courseteacherservice 的业务类impl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| package com.xuecheng.contentService.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.xuecheng.contentModel.po.CourseTeacher; import com.xuecheng.contentService.mapper.CourseTeacherMapper; import com.xuecheng.contentService.service.CourseTeacherService; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.List;
@Service public class CourseTeacherServiceImpl implements CourseTeacherService {
@Autowired CourseTeacherMapper courseTeacherMapper;
@Override public List<CourseTeacher> getCourseTeacherInfo(Long courseId) { LambdaQueryWrapper<CourseTeacher> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(CourseTeacher::getCourseId, courseId); CourseTeacher teacher = courseTeacherMapper.selectOne(queryWrapper); List<CourseTeacher> list = new ArrayList<>(); if (teacher == null){ list.add(new CourseTeacher()); }else { list.add(teacher); } return list; }
@Transactional @Override public CourseTeacher saveCourseTeacher(CourseTeacher teacher) { Long teacherCourseId = teacher.getCourseId(); LambdaQueryWrapper<CourseTeacher> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(CourseTeacher::getCourseId, teacherCourseId); Integer count = courseTeacherMapper.selectCount(queryWrapper); if (count < 1){ CourseTeacher courseTeacher = new CourseTeacher(); BeanUtils.copyProperties(teacher, courseTeacher); courseTeacherMapper.insert(courseTeacher); return getCourseTeacher(courseTeacher); } CourseTeacher courseTeacher = courseTeacherMapper.selectOne(queryWrapper); Long id = courseTeacher.getId(); BeanUtils.copyProperties(teacher, courseTeacher); courseTeacher.setId(id); courseTeacherMapper.updateById(courseTeacher); Long courseId = courseTeacher.getCourseId(); LambdaQueryWrapper<CourseTeacher> query = new LambdaQueryWrapper<>(); query.eq(CourseTeacher::getCourseId, courseId); return courseTeacherMapper.selectOne(query); }
private CourseTeacher getCourseTeacher(CourseTeacher courseTeacher) { Long courseId = courseTeacher.getCourseId(); LambdaQueryWrapper<CourseTeacher> query = new LambdaQueryWrapper<>(); query.eq(CourseTeacher::getCourseId, courseId); return courseTeacherMapper.selectOne(query); }
@Transactional @Override public void deleteCourseTeacher(Long courseId, Long id) { courseTeacherMapper.deleteById(id); } }
|
说明:
- 查询教师接口,前端必须要获取到值才能展示页面,对于自己新增的课程,第一次进入肯定是没有老师信息的,所以我是先创建一个空的教师信息,使前端能获取到然后展示到页面,再将这个空的教师信息在调用新增教师信息接口时用新的值覆盖掉,如果你有更好的方法可以自己改哦
- 添加教师接口 和 修改教师接口 前端调用的是同一个url,所以要写成一个,在后端进行判断是新增还是修改,但这里存在一个问题就是:这么写一个课程就只能存在一个老师,虽然也满足要求,但是后期可能会改动一下
接口测试
前后端联调,HTTPClient,swapper都行
删除课程
完成以实战内容需要将课程资料下的course-list.vue文件 覆盖 project-xczx2-portal-vue-
ts\src\module-organization\pages\course-manage\course-list.vue
需求分析
接口定义
1 2 3 4 5
| delete /course/ 87 为课程id
请求参数:课程id 响应:状态码 200 ,不返回信息
|
接口开发
删除课程,是在content工程的 courseBase中进行接口开发
model
略
api-接口定义
在 courseBaseInfoController 中 添加接口:
1 2 3 4
| @DeleteMapping("/course/{courseId}") public void deleteCourseBase(@PathVariable @Validated Long courseId){ courseBaseInfoService.deleteCourseBase(courseId); }
|
service-接口开发
创建service接口
在courseBase的service中创建接口:
1 2 3 4 5 6 7
|
public void deleteCourseBase(Long courseId);
|
创建service实现类impl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Transactional @Override public void deleteCourseBase(Long courseId) { LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(CourseBase::getId, courseId); CourseBase courseBase = courseBaseMapper.selectOne(queryWrapper); String status = courseBase.getStatus(); if (!status.equals("203001")) { throw new XueChengException("课程未处于未提交状态,无法删除"); } LambdaQueryWrapper<CourseTeacher> query3 = new LambdaQueryWrapper<>(); query3.eq(CourseTeacher::getCourseId, courseId); courseTeacherMapper.delete(query3);
LambdaQueryWrapper<TeachplanMedia> query2 = new LambdaQueryWrapper<>(); query2.eq(TeachplanMedia::getCourseId, courseId); teachplanMediaMapper.delete(query2);
LambdaQueryWrapper<Teachplan> query1 = new LambdaQueryWrapper<>(); query1.eq(Teachplan::getCourseId, courseId); teachplanMapper.delete(query1);
Long id = courseBase.getId(); courseMarketMapper.deleteById(id); courseBaseMapper.deleteById(id); }
|
这里有点憨,从后往前删了。。。不过问题不大
接口测试
直接前后端联调,删自己创建的课程,检查数据库多张表(基本信息、营销信息、课程计划、课程教师信息)的删除情况