前言
文章内容输出来源:拉勾教育JAVA就业训练营
1.联调准备
1.1 运行后台项目
- clean 清空项目的编译文件
- compile 重新编译项目
- 将项目部署到 tomcat
- 项目名为: lagou_edu_home
- 端口号: 8080
- 部署图片上传路径为 webapps目录下的 upload目录
1.2 运行前端项目
- 首先导入前端项目到 VSCode
- 运行项目.
2.课程管理首页
2.1 获取课程列表
JS部分
export default {
name: "Courses",
title: "课程管理",
//定义数据部分
data() {
return {
filter: { course_name: "", status: "" }, //查询对象
courses: [], //课程信息集合
loading: false //是否弹出加载
};
},
//钩子函数
created() {
this.loadCourses();
},
methods: {
//方法1: 获取课程列表
loadCourses() {
this.loading = true;
//请求后台查询课程列表接口
return axios
.get("/course", {
params: {
methodName: "findCourseList"
}
})
.then(resp => {
console.log(resp);
this.loading = false; //关闭加载
this.courses = resp.data; //取出数据
})
.catch(error => {
this.$message.error("数据获取失败! ! !");
});
},
}
};
</script>
2.2 条件查询课程信息
//方法2: 条件查询课程信息
filterQuery() {
this.loading = true;
//定义查询条件对象
const search = {};
//保存用户输入的条件
if (this.filter.course_name) search.course_name = this.filter.course_name;
if (this.filter.status) search.status = this.filter.status;
//请求后台条件查询接口
return axios
.get("/course", {
//准备参数
params: {
methodName: "findByCourseNameAndStatus",
course_name: search.course_name,
status: search.status
}
})
.then(resp => {
console.log(resp);
this.loading = false;
//将响应数据保存到 courses
this.courses = resp.data;
})
.catch(error => {
this.$message.error("数据获取失败! ! !");
});
},
2.3 跳转到添加课程
//方法3: 添加课程跳转方法
addCourse() {
//路由跳转到 CourseItem.vue组件
this.$router.push({ name: "CourseItem", params: { courseId: "new" } });
},
2.4 修改课程状态
//方法4: 修改课程状态
updateStatus(item) {
//item 表示选中的数据 = Course对象
axios
.get("/course", {
params: {
methodName: "updateCourseStatus",
id: item.id
}
})
.then(res => {
console.log(res);
//将返回的状态字段,封装到对象中
Object.assign(item, res.data);
//重新加载页面
window.location.reload;
});
},
2.5 跳转课程营销或内容管理
//方法5: 根据路由名称, 导航到对应组件
handleNavigate(name, id) {
this.$router.push({ name, params: { courseId: id } });
},
3.新建&修改课程
3.1 Course组件中的跳转方法
<!-- 营销信息按钮 -->
<el-button
size="mini"
@click="handleNavigate('CourseItem', scope.row.id)"
>营销信息</el-button>
>//方法3: 添加课程跳转方法
addCourse() {
//路由跳转到 CourseItem.vue组件
this.$router.push({ name: "CourseItem", params: { courseId: "new" } });
},
3.2 router.js 路由
找到name为: CourseItem的路由
//添加课程的路由
{
path: "/courses/:courseId", //路径,携带参数: 课程ID
name: "CourseItem",
//路由导航到的组件
component: () =>
import(/* webpackChunkName: 'courses' */ "../views/CourseItem.vue")
},
3.3 CourseItem组件
data() {
//数据
return {
rules, //规则
course: {}, //课程
loading: false,
params: {} //参数对象
};
},
//钩子函数
created() {
//1.获取路由传递的参数
const id = this.$route.params.courseId;
//2.判断id是否有值,没有值跳转到 错误页面
if (!id) return this.redirectToError();
//3.判断 是new 还是具体的id
if (id === "new") {
//new 代表新增,添加一个新增课程标题
this.course.title = "新增课程";
} else {
//否则就是修改,调用loadCourse方法进行回显
this.loadCourse(id);
}
},
3.3.2 图片上传分析
<!-- 上传图片部分 -->
<el-form-item label="分享小图" prop="share_image_title">
<el-input v-model="course.share_image_title" type="text">
<!-- :auto-upload="false",取消自动上传, :on-change="onchange" 调用onchange
进行处理 -->
<el-upload
slot="prepend"
:auto-upload="false"
:on-change="onchange"
action
:limit="1"
>
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</el-input>
</el-form-item>
FormData的主要用途有两个
- 将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,
提高工作效率。 - 异步上传文件
- 创建FormData对象
data中创建FormData
//5.创建FormData对象,将图片与表单一同上传
this.params = new FormData();
methods添加方法
//文件上传
onchange(file) {
//判断文件不为空
if (file != null) {
//将文件信息 保存到params中
this.params.append("file", file.raw, file.name);
}
},
3.3.3 新建课程信息
3.3.4 修改课程信息
4.内容管理
4.1 Course组件中的跳转方法
4.2 router.js 路由
//内容管理的路由
{
path: "/courses/:courseId/tasks",
name: "CourseTasks",
meta: { requireAuth: true },
component: () =>
import(/* webpackChunkName: 'courses' */ "../views/CourseTasks.vue")
}
# 4.3 CourseTasks组件
4.3.1 树形控件测试
- 打开我们之前编写的VueCLI项目
- 在component目录下,添加一个组件, TestTree.vue
- 在Index.vue组件中的导航菜单位置添加一个 树形控件导航.
注意:要设置index的路径为 /tree
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>导航菜单</span>
</template>
<el-menu-item-group>
<!-- 修改 index的路由地址 -->
<el-menu-item index="/course">
<i class="el-icon-menu"></i>课程管理
</el-menu-item>
<el-menu-item index="/tree">
<i class="el-icon-menu"></i>树形控件
</el-menu-item>
</el-menu-item-group>
</el-submenu>
- 在index.js
//导入树形控件组件
import TestTree from "@/components/TestTree";
//布局路由
{
path: "/index",
name: "index",
component: Index,
//添加子路由,使用 children属性 来表示子路由
children: [
//课程信息子路由
{
path: "/course",
name: "course",
component: Course,
},
//Tree控件测试路由
{
path: "/tree",
name: "tree",
component: TestTree,
},
],
},
- 路由文件中进行配置,在布局路由中再添加一个子路由
- 在ElementUI官网中查找树形控件
- Tree组件属性分析
- data: 展示数据
- props : 配置树形结构
- label : 设置节点名称
- children: 指定生成子树的属性名称
- 自定义树节点内容:
- data: 数据对象
- node: 节点对象
4.3.2 显示当前课程的名称
- 显示当前课程名称
<el-page-header
@back="() => this.$router.back()"
:content="addSectionForm.course_name"
/>
- data数据
- 加载课程信息
4.3.3 加载章节与课时信息
- el-tree ElementUI树形控件
:data 列表数据
:props 配置选项
<!-- 树形控件,展示课程对应的章节信息 -->
<el-tree
:data="sections"
:props="treeProps"
v-loading="loading"
element-loading-text="数据加载中..."
>
<!-- slot-scope:代表当前树节点内容,有两个参数 data表示当前树节点, node表示当前节点
状态 -->
<div class="inner" slot-scope="{ data, node }">
<span>{{ data.section_name || data.theme }}</span>
- :props 配置选项
label : 指定节点标签为节点对象的某个属性值
children : 指定子树为节点对象的某个属性值
//章节与课时信息,树形结构
const treeProps = {
label: item => {
return item.section_name || item.theme;
},
children: "lessonList"
};
//children: "lessonList" 就是返回的JSON数据中的lessonList集合
- 操作按钮显示
node.level 获取当前节点的级别
@click.stop 事件冒泡,点击哪个元素,就执行哪个元素绑定的事件
<span class="actions">
<!-- 编辑章节 @click.stop 阻止事件冒泡 -->
<el-button
v-if="node.level == 1"
size="small"
@click.stop="handleEditSection(data)"
>编辑</el-button
>
<!-- 修改章节状态 -->
<el-button
v-if="node.level == 1"
size="small"
@click.stop="handleShowToggleStatus(data)"
>{{ statusMapping[data.status] }}</el-button
>
</span>
4.3.4 回显信息
<el-button type="primary" icon="el-icon-plus" @click="handleShowAddSection">添加
章节</el-button>
//方法3: 显示添加章节表单,回显课程信息
handleShowAddSection() {
//显示表单
this.showAddSection = true;
},
```
### 4.3.5 添加章节
### 4.3.6 后台接口问题解决
if(“application/json;charset=utf-8”.equals(contentType))
修改为:
if(“application/json;charset=utf-8”.equalsIgnoreCase(contentType))
### 4.3.7 修改章节
事件冒泡:当点击子元素的事件。如果父元素也有同样的事件的话。他就会一并的触发。
解决冒泡事件的方法: @click.stop
````js
<body>
<!-- 事件冒泡: 解决方案 @click.stop -->
<div id="app" @click="log('div点击事件')">
<button @click="log('button点击事件')">事件冒泡</button>
</div>
</body>
<script src="./js/vue.min.js"></script>
<script>
var VM = new Vue({
el: "#app",
methods: {
log(t) {
alert(t);
},
},
});
</script>
4.3.8 章节状态回显
4.3.9 章节状态修改
- v-for里面数据层次太多, 修改过数据变了,页面没有重新渲染,需手动强制刷新。
@change="$forceUpdate()" 强制刷新