目录
1.1.3、测试异常:Invalid bound statement (not found)
1、确认信息的显示
1.1、后端
1.1.1、定义确认信息 VO
@Data
@ApiModel(value = "课程确认信息")
public class CoursePublishVO {
private String courseId;
private String title;
private String cover;
private Integer lessonNum;
private String subjectLevelOne;
private String subjectLevelTwo;
private String teacherName;
private String price;//只用于显示
}
1.1.2、根据课程 ID 获取确认信息
在 EduCourseMapper.xml 添加查询 SQL
<!-- 根据课程ID查询课程确认信息 -->
<select id="getPublishCourseInfo" resultType="com.zyj.eduservice.entity.vo.CoursePublishVO">
SELECT ec.`id`, ec.`title`, ec.`price`, ec.`lesson_num` AS lessonNum, ec.`cover`,
et.`name` AS teacherName,
es1.`title` AS subjectLevelOne,
es2.`title` AS subjectLevelTwo
FROM `edu_course` ec LEFT OUTER JOIN `edu_teacher` et ON ec.`teacher_id` = et.`id`
LEFT OUTER JOIN `edu_subject` es1 ON ec.`subject_parent_id` = es1.`id`
LEFT OUTER JOIN `edu_subject` es2 ON ec.`subject_id` = es2.`id`
WHERE ec.`id` = '1586554891470389250';
</select>
EduCourseMapper
/**
* 根据课程ID查询课程确认信息
* @param courseId 课程ID
* @return
*/
public CoursePublishVO getPublishCourseInfo(String courseId);
EduCourseService
/**
* 根据课程ID查询课程确认信息
* @param courseId 课程ID
* @return
*/
CoursePublishVO publishCourseInfo(String courseId);
EduCourseServiceImpl
/**
* 根据课程ID查询课程确认信息
* @param courseId 课程ID
* @return
*/
@Override
public CoursePublishVO publishCourseInfo(String courseId) {
CoursePublishVO publishCourseInfo = baseMapper.getPublishCourseInfo(courseId);
return publishCourseInfo;
}
EduCourseController
/**
* 根据课程ID查询课程确认信息
* @param courseId 课程ID
* @return
*/
@GetMapping("/getPublishCourseInfo/{courseId}")
public R getPublishCourseInfo(
@ApiParam(name = "courseId", value = "课程ID", required = true) @PathVariable String courseId
) {
CoursePublishVO coursePublishVO = courseService.publishCourseInfo(courseId);
return R.ok().data("coursePublishVO", coursePublishVO);
}
1.1.3、测试异常:Invalid bound statement (not found)
此时测试会报异常 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found),即找不到在 mapper.xml 中定义 SQL 语句。
这个错误是由 maven 默认加载机制造成的:maven 加载时,只会把 src/main/java 文件夹里面的 .java 类型文件进行编译,如果其他类型文件,不会加载
解决方法:
- 复制 xml 到 target 文件夹(不推荐)
- 把 xml 文件放到 resources 目录下(不推荐:破坏项目结构)
- (推荐)通过配置实现:在 pom.xml 和 项目 application.properties 中配置
这里使用第三种方法来解决
在 service\pom.xml 中配置
<!-- 项目打包时会将java目录中的*.xml文件也进行打包 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
然后在 src/main/resources/application.properties 中配置
# 配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/zyj/eduservice/mapper/xml/*.xml
配置完后刷新 maven,重启服务,就可以运行了
1.2、前端
1.2.1、定义 API
src\api\edu\course.js
/**
* 根据课程ID查询课程确认信息
* @param {*} courseId
* @returns
*/
getPublishCourseInfo(courseId) {
return request({
url: `/eduservice/course/getPublishCourseInfo/${courseId}`,
method: 'GET',
})
}
并在 src\views\edu\course\publish.vue 中引入
import course from '@/api/edu/course.js'
1.2.2、定义数据模型
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用
courseId: '', // 课程ID
publishCourse: {} // 课程确认信息
}
},
1.2.3、完善步骤导航
/**
* 点击上一步跳转到src\views\edu\course\chapter.vue
*/
previous() {
this.$router.push({ path: '/course/chapter/' + this.courseId });
},
1.2.4、页面组件
显示确认信息
<div class="ccInfo">
<img :src="publishCourse.cover">
<div class="main">
<h2>{{ publishCourse.title }}</h2>
<p class="gray"><span>共{{ publishCourse.lessonNum }}课时</span></p>
<p><span>所属分类:{{ publishCourse.subjectLevelOne }} — {{ publishCourse.subjectLevelTwo }}</span></p>
<p>课程讲师:{{ publishCourse.teacherName }}</p>
<h3 class="red">¥{{ publishCourse.price }}</h3>
</div>
</div>
样式:
<style scoped>
.ccInfo {
background: #f5f5f5;
padding: 20px;
overflow: hidden;
border: 1px dashed #DDD;
margin-bottom: 40px;
position: relative;
}
.ccInfo img {
background: #d6d6d6;
width: 500px;
height: 278px;
display: block;
float: left;
border: none;
}
.ccInfo .main {
margin-left: 520px;
}
.ccInfo .main h2 {
font-size: 28px;
margin-bottom: 30px;
line-height: 1;
font-weight: normal;
}
.ccInfo .main p {
margin-bottom: 10px;
word-wrap: break-word;
line-height: 24px;
max-height: 48px;
overflow: hidden;
}
.ccInfo .main p {
margin-bottom: 10px;
word-wrap: break-word;
line-height: 24px;
max-height: 48px;
overflow: hidden;
}
.ccInfo .main h3 {
left: 540px;
bottom: 20px;
line-height: 1;
font-size: 28px;
color: #d32f24;
font-weight: normal;
position: absolute;
}
</style>
1.2.5、获取确认信息
在 methods 中定义
/**
* 获取当前课程ID的确认信息
*/
getPublishCourseInfo() {
course.getPublishCourseInfo(this.courseId).then(response => {
this.publishCourse = response.data.coursePublishVO;
});
}
在 created 中获取
created() {
// 获取路由中的课程ID并获取信息
if(this.$route.params && this.$route.params.id) {
this.courseId = this.$route.params.id;
this.getPublishCourseInfo();
}
},
2、课程发布
2.1、后端
2.1.1、发布指定课程 ID 的课程
EduCourseController
/**
* 发布指定ID的课程:修改课程状态即可
* @param courseId 课程ID
* @return
*/
@PostMapping("/publishCourse/{courseId}")
public R publishCourse(
@ApiParam(name = "courseId", value = "课程ID", required = true) @PathVariable String courseId
) {
EduCourse eduCourse = new EduCourse();
eduCourse.setId(courseId);
eduCourse.setStatus("Normal");
courseService.updateById(eduCourse);
return R.ok();
}
2.2、后端
2.2.1、定义 API
src\api\edu\course.js
/**
* 发布指定ID的课程
* @param {*} courseId 课程ID
* @returns
*/
publishCourse(courseId) {
return request({
url: `/eduservice/course/publishCourse/${courseId}`,
method: 'POST'
})
}
2.2.2、发布课程
在 methods 中定义
/**
* 发布课程
*/
publish() {
this.$confirm('是否发布该课程?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
// 确认发布
.then(() => {
course.publishCourse(this.courseId).then(response => {
// 提示信息
this.$message({
type: 'success',
message: '发布成功!'
});
// 跳转到课程列表页面
this.$router.push({ path: '/course/table' })
})
})
// 取消发布
.catch(() => {
this.$message({
type: 'info',
message: '已取消发布'
});
});
}
3、完整页面
<template>
<div class="app-container">
<h2 style="text-align: center;">发布新课程</h2>
<el-steps :active="3" process-status="wait" align-center style="margin-bottom: 40px;">
<el-step title="填写课程基本信息" />
<el-step title="创建课程大纲" />
<el-step title="发布课程" />
</el-steps>
<div class="ccInfo">
<img :src="publishCourse.cover">
<div class="main">
<h2>{{ publishCourse.title }}</h2>
<p class="gray"><span>共{{ publishCourse.lessonNum }}课时</span></p>
<p><span>所属分类:{{ publishCourse.subjectLevelOne }} — {{ publishCourse.subjectLevelTwo }}</span></p>
<p>课程讲师:{{ publishCourse.teacherName }}</p>
<h3 class="red">¥{{ publishCourse.price }}</h3>
</div>
</div>
<div>
<el-button @click="previous">返回修改</el-button>
<el-button :disabled="saveBtnDisabled" type="primary" @click="publish">发布课程</el-button>
</div>
</div>
</template>
<script>
import course from '@/api/edu/course.js'
export default {
data() {
return {
saveBtnDisabled: false, // 保存按钮是否禁用
courseId: '', // 课程ID
publishCourse: { // 课程确认信息
}
}
},
created() {
// 获取路由中的课程ID并获取信息
if(this.$route.params && this.$route.params.id) {
this.courseId = this.$route.params.id;
this.getPublishCourseInfo();
}
},
methods: {
/**
* 点击上一步跳转到src\views\edu\course\chapter.vue
*/
previous() {
this.$router.push({ path: '/course/chapter/' + this.courseId });
},
/**
* 获取当前课程ID的确认信息
*/
getPublishCourseInfo() {
course.getPublishCourseInfo(this.courseId).then(response => {
this.publishCourse = response.data.coursePublishVO;
});
},
/**
* 发布课程
*/
publish() {
this.$confirm('是否发布该课程?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
// 确认发布
.then(() => {
course.publishCourse(this.courseId).then(response => {
// 提示信息
this.$message({
type: 'success',
message: '课程发布成功!'
});
// 跳转到课程列表页面
this.$router.push({ path: '/course/table' })
})
})
// 取消发布
.catch(() => {
this.$message({
type: 'info',
message: '已取消发布'
});
});
}
}
}
</script>
<style scoped>
.ccInfo {
background: #f5f5f5;
padding: 20px;
overflow: hidden;
border: 1px dashed #DDD;
margin-bottom: 40px;
position: relative;
}
.ccInfo img {
background: #d6d6d6;
width: 500px;
height: 278px;
display: block;
float: left;
border: none;
}
.ccInfo .main {
margin-left: 520px;
}
.ccInfo .main h2 {
font-size: 28px;
margin-bottom: 30px;
line-height: 1;
font-weight: normal;
}
.ccInfo .main p {
margin-bottom: 10px;
word-wrap: break-word;
line-height: 24px;
max-height: 48px;
overflow: hidden;
}
.ccInfo .main p {
margin-bottom: 10px;
word-wrap: break-word;
line-height: 24px;
max-height: 48px;
overflow: hidden;
}
.ccInfo .main h3 {
left: 540px;
bottom: 20px;
line-height: 1;
font-size: 28px;
color: #d32f24;
font-weight: normal;
position: absolute;
}
</style>