目录
一、第五天内容介绍
讲师管理前端开发
1、讲师列表(分页条件查询)
2、讲师添加
3、讲师删除功能
4、讲师修改功能
vue-admin-template模块进行前端开发
基于 vue + element-ui
首先,把后台管理系统登录改造工地(临时)后面把登录添加权限框架spring secuitry
二、把系统登录功能改造本地
1、系统登录默认使用这个地址
![]()
把登录请求地址改造本地 http://localhost:8001
2、修改配置文件请求地址
在config文件夹里面有dev.env.js
// 登录
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
return new Promise((resolve, reject) => {
login(username, userInfo.password).then(response => {
const data = response.data
setToken(data.token)
commit('SET_TOKEN', data.token)
resolve()
}).catch(error => {
reject(error)
})
})
},注意 :是http不是https
http和https区别
https个人使用没有权限,需要找相关部门认证才行
3、进行登录调用两个方法:
login登录操作方法
info登录之后获取用户信息的方法,
所以,创建接口两个方法实现登录
(1)login 返回 token值
// 登录
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
return new Promise((resolve, reject) => {
login(username, userInfo.password).then(response => {
const data = response.data
setToken(data.token)
commit('SET_TOKEN', data.token)
resolve()
}).catch(error => {
reject(error)
})
})
},(2)info返回 roles name avatar(头像)
// 获取用户信息
GetInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo(state.token).then(response => {
const data = response.data
if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', data.roles)
} else {
reject('getInfo: roles must be a non-null array !')
}
commit('SET_NAME', data.name)
commit('SET_AVATAR', data.avatar)
resolve(response)
}).catch(error => {
reject(error)
})
})
},这两个方法在user.js中

4、开发接口
(1)先创建

(2)写接口中的方法
package com.atguigu.eduservice.controller;
import com.atguigu.commonutils.R;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/eduservice/user")
public class EduLoginController {
//login
@PostMapping("login")
public R login(){
return R.ok().data("token","admin");
}
//info
@GetMapping("info")
public R info(){
return R.ok().data("roles","[admin]").data("name","admin").data("avatar","https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
}
}
5、修改api文件login.js修改本地接口路径
(1)修改login地址

(2)修改info地址

6、最终测试,出现问题
![]()
![]()
跨域问题:通过一个地址去访问另外一个地址,这个过程中有三个地方有任何一个不一样
访问协议 http https
ip地址 192.168.1.1 172.11.11.11
端口号 9258 8001
前端端口: http://localhost:9528/
端口不一样,产生跨域问题
7、跨域解决方式
(1)在后端接口controller添加注解(常用)

(2)使用网关解决(后面讲到)
8、测试
注意:如果发现成功但没跳转页面,记得看一common中的状态码

将code改为20000
package com.atguigu.commonutils;
public interface ResultCode {
public static Integer SUCCESS = 20000;//成功
public static Integer ERROR = 20001;//操作失败
}
成功页面

两次 第一次测连通 第二次发请求

三、框架使用过程
第一步 添加路由

第二步 点击某个路由,显示路由对应页面内容

跳到对应页面

第三步 在api文件夹创建js文件,定义接口地址和参数

第四步 在创建vue页面引入js文件,调用方法实现功能
引入 import user from '...'
data:{
},
created(){
},
methods:{
}最后使用element-ui显示数据内容
3.1 讲师列表前端实现
第一步 添加路由


第二步 创建路由对应的页面


路径不要写错 我的宝们
list.vue
<template>
<div class="app-container">
讲师列表
</div>
</template>
效果展示

save.vue
<template>
<div class="app-container">
讲师添加
</div>
</template>
效果展示

第三步 在api文件创建teacher.js定义访问的接口地址

teacher.js代码如下
/* eslint-disable no-undef */
import request from '@/utils/request'
export default {
// 1 讲师列表(条件查询分页)
// current当前页 limit分页 teacherQuery条件对象
getTeacherListPage(current, limit, teacherQuery) {
return request({
//url: '/table/list/'+current+"/"+limit,
url: `/eduservice/teacher/pageTeacherCondition/${current}/${limit}`,
method: 'post',
//teacherQuery条件对象,后端使用RequestBody获取数据
//data 表示把对象转换为json进行传递到接口里面
data: teacherQuery
})
}
}
第四步 在讲师列表页面 list.vue页面调用定义的接口方法,得到接口返回数据
<template>
<div class="app-container">
讲师列表
</div>
</template>
<script>
//引入调用teacher.js文件
import teacher from '@/api/edu/teacher'
export default {
//写核心代码位置
// data:{
// },
data() { //定义边和和初始值
return {
list:null,//查询之后接口返回集合
page:1,//当前页
limit:10,//每页记录数
total:0,//总记录数
teacherQuery:{} //条件封装对象
};
},
created() { // 在页面渲染之前执行,一般调用methods定义的方法
//调用
this.getList()
},
methods: { // 创建具体的方法,调用teacher.js定义的方法
//讲师列表的方法
getList(){
teacher.getTeacherListPage(this.page,this.limit,this.teacherQuery)
.then(response =>{//请求成功
//response 接口返回的数据
this.list = response.data.rows
this.total = response.data.total
console.log(this.list)
console.log(this.total)
})
.catch(error =>{
console.log(error)
})//请求失败
}
}
}
</script>
浏览器输出效果

第五步 把请求接口获取数据在页面进行显示
使用组件 Element-ui 网址 Element - The world's most popular Vue UI framework
5.1 点开Table表格

5.2 点开隐藏代码

表格的代码如下
<el-table
:data="list"
border
fit
highlight-current-row>
<el-table-column
label="序号"
width="70"
align="center">
<template slot-scope="scope">
{{ (page - 1) * limit + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="名称" width="80" />
<el-table-column label="头衔" width="80">
<template slot-scope="scope">
{{ scope.row.level===1?'高级讲师':'首席讲师' }}
</template>
</el-table-column>
<el-table-column prop="intro" label="资历" />
<el-table-column prop="gmtCreate" label="添加时间" width="160"/>
<el-table-column prop="sort" label="排序" width="60" />
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<router-link :to="'/teacher/edit/'+scope.row.id">
<el-button type="primary" size="mini" icon="el-icon-edit">修改</el-button>
</router-link>
<el-button type="danger" size="mini" icon="el-icon-delete" @click="removeDataById(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
5.3效果展示
第六步 分页组件
6.1原始代码
<!-- 分页 -->
<el-pagination
:current-page="page"
:page-size="limit"
:total="total"
style="padding: 30px 0; text-align: center;"
layout="total, prev, pager, next, jumper"
@current-change="fetchData"
/>修改后的代码
<!-- 分页 -->
<el-pagination
:current-page="page"
:page-size="limit"
:total="total"
style="padding: 30px 0; text-align: center;"
layout="total, prev, pager, next, jumper"
@current-change="getList"
/>修改getList方法
getList(page = 1){
this.page= page
teacher.getTeacherListPage(this.page,this.limit,this.teacherQuery)
.then(response =>{//请求成功
//response 接口返回的数据
this.list = response.data.rows
this.total = response.data.total
console.log(this.list)
console.log(this.total)
})
.catch(error =>{
console.log(error)
})//请求失败
}效果展示

6.2 添加条件查询
注意:element-ui的 date-picker组件默认绑定的时间值是默认世界标准时间,和中国时间差8小时
原始代码
<!--查询表单-->
<el-form :inline="true" class="demo-form-inline">
<el-form-item>
<el-input v-model="searchObj.name" placeholder="讲师名" />
</el-form-item>
<el-form-item>
<el-select v-model="searchObj.level" clearable placeholder="讲师头衔">
<el-option :value="1" label="高级讲师" />
<el-option :value="2" label="首席讲师" />
</el-select>
</el-form-item>
<el-form-item label="添加时间">
<el-date-picker
v-model="searchObj.begin"
type="datetime"
placeholder="选择开始时间"
value-format="yyyy-MM-dd HH:mm:ss"
default-time="00:00:00"
/>
</el-form-item>
<el-form-item>
<el-date-picker
v-model="searchObj.end"
type="datetime"
placeholder="选择截止时间"
value-format="yyyy-MM-dd HH:mm:ss"
default-time="00:00:00"
/>
</el-form-item>
<el-button type="primary" icon="el-icon-search" @click="fetchData()">查 询</el-button>
<el-button type="default" @click="resetData()">清空</el-button>
</el-form>
情况功能
(1)清空表单输入条件数据
(2)查询所有的数据
resetData(){// 清空的方法
//表单输入项数据清空
this.teacherQuery = {}
//查询所有讲师数据
this.getList
}6.3 讲师删除功能
1、在每条记录后添加 删除按键
2、在按键绑定事件
![]()
3、在绑定事件的方法传递删除讲师id值
![]()
4、在api文件夹teacher.js定义删除接口的地址
//删除讲师
deleteTeacherId(id){
return request({
url: `/eduservice/teacher/${id}`,
method: 'delete',
})
}5、页面调用,实现方法
从用户体验来看 应该加个提示框
Element-ui代码
// debugger
// console.log(memberId)
this.$confirm("此操作将永久删除该记录, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
return teacher.removeById(id);
})
.then(() => {
this.fetchData();
this.$message({
type: "success",
message: "删除成功!",
});
})
.catch((response) => {
// 失败
if (response === "cancel") {
this.$message({
type: "info",
message: "已取消删除",
});
} else {
this.$message({
type: "error",
message: "删除失败",
});
}
});修改后的代码
this.$confirm("此操作将永久删除讲师记录, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => { // 点击确定,执行then方法
teacher.deleteTeacherId(id)
.then(response => {//删除成功
//提示消息
this.$message({
type: "success",
message: "删除成功!",
});
//回到列表页面
this.getList()
})
})
}效果展示

我们删除王刚

数据王刚的is_deleted变为1 逻辑删除成功
6.4 添加讲师功能
1.点击添加讲师按钮 进入表单页面,输入讲师信息
Element-ui 代码
<el-form label-width="120px">
<el-form-item label="讲师名称">
<el-input v-model="teacher.name" />
</el-form-item>
<el-form-item label="讲师排序">
<el-input-number v-model="teacher.sort" controls-position="right" :min="0"/>
</el-form-item>
<el-form-item label="讲师头衔">
<el-select v-model="teacher.level" clearable placeholder="请选择">
<!--
数据类型一定要和取出的json中的一致,否则没法回填
因此,这里value使用动态绑定的值,保证其数据类型是number
-->
<el-option :value="1" label="高级讲师" />
<el-option :value="2" label="首席讲师" />
</el-select>
</el-form-item>
<el-form-item label="讲师资历">
<el-input v-model="teacher.career" />
</el-form-item>
<el-form-item label="讲师简介">
<el-input v-model="teacher.intro" :rows="10" type="textarea" />
</el-form-item>
<!-- 讲师头像:TODO -->
<el-form-item>
<el-button :disabled="saveBtnDisabled" type="primary" @click="saveOrUpdate">保存</el-button>
</el-form-item>
</el-form>
在表单页面点击保存,提交接口,添加数据
(1)定义接口地址,修改api下teaher.js
//添加讲师
addTeacher(teacher){
return request({
url: `/eduservice/teacher/addTeacher`,
method: 'post',
data:teacher
})
}(2)在页面实现调用
先进行引入 ![]()
代码
//添加讲师的方法
SaveTeacher(){
teacherApi.addTeacher(this.teacher)
.then(response => {// 添加成功
//提示信息
//提示消息
this.$message({
type: "success",
message: "添加成功!",
});
//回到列表页面 路由跳转
this.$router.push({path:'/teacher/table'})
})
}测试

6.4 讲师修改功能
1、每条几率后面添加 修改 按钮
2、点击修改按钮,进入表单页面,进行数据库回显
根据讲师id查询数据显示
3、通过路由跳转进入数据回显页面,在路由index页面添加路由
{
path: 'edit/:id',
name: 'EduTeacherEdit',
component: () => import('@/views/edu/teacher/save'),
meta: { title: '编辑讲师', noCache: 'tree' },
hidden: true
}
页面显示

4、在表单页面实现数据回显
(1)在teacher.js定义根据id查询接口
getTeacherInfo(id){
return request({
url: `/eduservice/teacher/getTeacher/${id}`,
method: 'get'
})
}(2)在页面调用接口实现回显
//根据讲师id查询的方法
getInfo(id){
teacherApi.getTeacherInfo(id)
.then(response => {
this.teacher = response.data.teacher;
})
},(3)调用 根据id查询的方法
因为添加和修改使用save页面 区别添加还是修改,只有修改时查询数据回显
区别添加还是修改,只有修改时候查询数据回显
判断路径里面是否含有讲师id值,如果有id值为修改,没有id值则为添加
if (this.$route.params && this.$route.params.id) {
//从路径获取id值
const id = this.$route.params.id;
//调用根据id查询的方法
this.getInfo(id);
}5、最终修改实现
1、在api的teacher.js定义接口
//修改讲师
updateTeacherInfo(teacher) {
return request({
url: `/eduservice/teacher/updateTeacher`,
method: 'post',
data: teacher
})
},2、在页面调用
判断为修改还是添加 根据id判断
saveOrUpdate() {
//判断修改还是添加
//根据teacher是否有id 有id为修改 否则就是添加
if(!this.teacher.id){
//添加
this.saveTeacher()
}else{
//修改
this.updateTeacher()
}
},修改讲师的方法
//修改讲师的方法
updateTeacher(){
teacherApi.updateTeacherInfo(this.teacher)
.then(response => {
//提示信息
this.$message({
type: "success",
message: "修改成功!",
});
//回到列表页面 路由跳转
this.$router.push({ path: "/teacher/table" });
})
},测试


四、存在的问题
1、第一次点击修改 进行数据回显
第二次再去点击 添加讲师,进入表单页面,遇到问题:表单页面还是显示修改回显的数据,正确效果应该是表单数据清空
解决方式:
做添加讲师的时候,表单数据清空就可以了
created() {
//页面渲染之前执行
//判断路径是否有id值
if (this.$route.params && this.$route.params.id) {
//从路径获取id值
const id = this.$route.params.id;
//调用根据id查询的方法
this.getInfo(id);
}else{ //路径没有id值,做添加
//清空表单代码
this.teacher = {}
}
},上面代码没有解决问题,为什么?
多次路由跳转到同一个页面,在页面中created方法只会执行一次,后面再进行跳转不会执行的
最终解决:使用vue监听
watch:{ // 监听
$route(to,from) { //路由变化方式,路由发生变化方法执行
this.init()
}
},抽取init方法
init(){
//判断路径是否有id值
if (this.$route.params && this.$route.params.id) {
//从路径获取id值
const id = this.$route.params.id;
//调用根据id查询的方法
this.getInfo(id);
}else{ //路径没有id值,做添加
//清空表单代码
this.teacher = {}
}测试通过