vue-admin-template是基于vue-element-admin的一套后台管理系统基础模板;最少精简版;;可作为模板进行二次开发。
GitHub地址;https://github.com/PanJiaChen/vue-admin-template
# 解压压缩包
# 进入目录
cd vue-admin-template-master
# 安装依赖
npm install
# 启动。执行后;浏览器自动弹出并访问http://localhost:9528/
npm run dev
创建LoginController
;RestController
;RequestMapping(;/admin/vod/user;)
;CrossOrigin
public class LoginController {
/**
* 登录
* ;return
*/
;PostMapping(;login;)
public Result login() {
Map<String, Object> map = new HashMap<>();
map.put(;token;,;admin;);
return Result.ok(map);
}
/**
* 获取用户信息
* ;return
*/
;GetMapping(;info;)
public Result info() {
Map<String, Object> map = new HashMap<>();
map.put(;roles;,;[admin];);
map.put(;name;,;admin;);
map.put(;avatar;,;https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg;);
return Result.ok(map);
}
/**
* 退出
* ;return
*/
;PostMapping(;logout;)
public Result logout(){
return Result.ok();
}
}
import request from ;;/utils/request;
export function login(data) {
return request({
url: ;/admin/vod/user/login;,
method: ;post;,
data
})
}
export function getInfo(token) {
return request({
url: ;/admin/vod/user/info;,
method: ;get;,
params: { token }
})
}
export function logout() {
return request({
url: ;/admin/vod/user/logout;,
method: ;post;
})
}
;1;浏览器从一个域名的网页去请求另一个域名的资源时;域名、端口、协议任一不同;都是跨域 。前后端分离开发中;需要考虑ajax跨域的问题。
;2;跨域的本质;浏览器对Ajax请求的一种限制
;3;这里我们可以从服务端解决这个问题
在Controller类上添加注解
;CrossOrigin //跨域
修改 src/router/index.js 文件;重新定义constantRouterMap
**注意;**每个路由的name不能相同
export const constantRouterMap = [
{ path: ;/login;, component: () => import(;;/views/login/index;), hidden: true },
{ path: ;/404;, component: () => import(;;/views/404;), hidden: true },
// 首页
{
path: ;/;,
component: Layout,
redirect: ;/dashboard;,
name: ;Dashboard;,
children: [{
path: ;dashboard;,
component: () => import(;;/views/dashboard/index;),
meta: { title: ;硅谷课堂后台管理系统;, icon: ;dashboard; }
}]
},
// 讲师管理
{
path: ;/vod;,
component: Layout,
redirect: ;/vod/course/list;,
name: ;Vod;,
meta: {
title: ;点播管理;,
icon: ;el-icon-bank-card;
},
alwaysShow: true,
children: [
{
path: ;teacher/list;,
name: ;TeacherList;,
component: () => import(;;/views/vod/teacher/list;),
meta: { title: ;讲师列表; }
},
{
path: ;teacher/create;,
name: ;TeacherCreate;,
component: () => import(;;/views/vod/teacher/form;),
meta: { title: ;添加讲师; },
hidden: true
},
{
path: ;teacher/edit/:id;,
name: ;TeacherEdit;,
component: () => import(;;/views/vod/teacher/form;),
meta: { title: ;编辑讲师; },
hidden: true
}
]
},
{ path: ;*;, redirect: ;/404;, hidden: true }
]
在src/views文件夹下创建以下文件夹和文件
<template>
<div class=;app-container;>
讲师表单
</div>
</template>
<template>
<div class=;app-container;>
讲师列表
</div>
</template>
创建文件 src/api/vod/teacher.js
import request from ;;/utils/request;
const api_name = ;/admin/vod/teacher;
export default {
//讲师列表
pageList(page, limit, searchObj) {
return request({
url: ;${api_name}/${page}/${limit};,
method: ;post;,
data: searchObj
})
}
}
src/views/vod/teacher/list.vue
<template>
<div class=;app-container;>
jiang;shi列表
</div>
</template>
<script>
import teacherApi from ;;/api/vod/teacher;
export default {
// 定义数据模型
data() {
return {
}
},
// 页面渲染成功后获取数据
created() {
this.fetchData()
},
// 定义方法
methods: {
fetchData() {
}
}
}
</script>
// 定义数据模型
data() {
return {
list: [], // 讲师列表
total: 0, // 总记录数
page: 1, // 页码
limit: 10, // 每页记录数
searchObj: {}, // 查询条件
multipleSelection: []// 批量删除选中的记录列表
}
},
methods: {
fetchData() {
// 调用api
teacherApi.pageList(this.page, this.limit, this.searchObj).then(response => {
debugger
this.list = response.data.records
this.total = response.data.total
})
},
}
<!-- 表格 -->
<el-table
:data=;list;
border
stripe
;selection-change=;handleSelectionChange;>
<el-table-column type=;selection;/>
<el-table-column
label=;#;
width=;50;>
<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=;90;>
<template slot-scope=;scope;>
<el-tag v-if=;scope.row.level === 1; type=;success; size=;mini;>高级讲师</el-tag>
<el-tag v-if=;scope.row.level === 0; size=;mini;>首席讲师</el-tag>
</template>
</el-table-column>
<el-table-column prop=;intro; label=;简介; />
<el-table-column prop=;sort; label=;排序; width=;60; />
<el-table-column prop=;joinDate; label=;入驻时间; width=;160; />
<el-table-column label=;操作; width=;200; align=;center;>
<template slot-scope=;scope;>
<el-button type=;text; size=;mini; ;click=;removeById(scope.row.id);>删除</el-button>
<router-link :to=;;/vod/teacher/edit/;;scope.row.id;>
<el-button type=;text; size=;mini;>修改</el-button>
</router-link>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<el-pagination
:current-page=;page;
:total=;total;
:page-size=;limit;
:page-sizes=;[5, 10, 20, 30, 40, 50, 100];
style=;padding: 30px 0; text-align: center;;
layout=;total, sizes, prev, pager, next, jumper;
;size-change=;changePageSize;
;current-change=;changeCurrentPage;
/>
<!--查询表单-->
<el-card class=;operate-container; shadow=;never;>
<el-form :inline=;true; class=;demo-form-inline;>
<el-form-item label=;名称;>
<el-input v-model=;searchObj.name; placeholder=;讲师名; />
</el-form-item>
<el-form-item label=;头衔;>
<el-select v-model=;searchObj.level; clearable placeholder=;头衔;>
<el-option value=;1; label=;高级讲师;/>
<el-option value=;0; label=;首席讲师;/>
</el-select>
</el-form-item>
<el-form-item label=;入驻时间;>
<el-date-picker
v-model=;searchObj.joinDateBegin;
placeholder=;开始时间;
value-format=;yyyy-MM-dd; />
</el-form-item>
<el-form-item label=;-;>
<el-date-picker
v-model=;searchObj.joinDateEnd;
placeholder=;结束时间;
value-format=;yyyy-MM-dd; />
</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>
</el-card>
分页和清空方法
// 每页记录数改变;size;回调参数;表示当前选中的“每页条数”
changePageSize(size) {
this.limit = size
this.fetchData()
},
// 改变页码;page;回调参数;表示当前选中的“页码”
changeCurrentPage(page) {
this.page = page
this.fetchData()
},
// 重置表单
resetData() {
this.searchObj = {}
this.fetchData()
},
src/api/vod/teacher.js
removeById(id) {
return request({
url: ;${api_name}/remove/${id};,
method: ;delete;
})
},
src/views/vod/teacher/list.vue
使用MessageBox 弹框组件
// 根据id删除数据
removeById(id) {
this.$confirm(;此操作将永久删除该记录, 是否继续?;, ;提示;, {
confirmButtonText: ;确定;,
cancelButtonText: ;取消;,
type: ;warning;
}).then(() => {
return teacherApi.removeById(id)
}).then((response) => {
this.fetchData()
this.$message.success(response.message)
})
},
src/api/vod/teacher.js
save(teacher) {
return request({
url: ;${api_name}/save;,
method: ;post;,
data: teacher
})
},
src/views/vod/teacher/form.vue
<template>
<div class=;app-container;>
<!-- 输入表单 -->
<el-form label-width=;120px;>
<el-form-item label=;讲师名称;>
<el-input v-model=;teacher.name; />
</el-form-item>
<el-form-item label=;入驻时间;>
<el-date-picker v-model=;teacher.joinDate; value-format=;yyyy-MM-dd; />
</el-form-item>
<el-form-item label=;讲师排序;>
<el-input-number v-model=;teacher.sort; :min=;0;/>
</el-form-item>
<el-form-item label=;讲师头衔;>
<el-select v-model=;teacher.level;>
<!--
数据类型一定要和取出的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.intro;/>
</el-form-item>
<el-form-item label=;讲师资历;>
<el-input v-model=;teacher.career; :rows=;10; type=;textarea;/>
</el-form-item>
<!-- 讲师头像 -->
<el-form-item label=;讲师头像;>
</el-form-item>
<el-form-item>
<el-button type=;primary; ;click=;saveOrUpdate();>保存</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import teacherApi from ;;/api/vod/teacher;
export default {
data() {
return {
BASE_API: ;http://localhost:8301;,
// 初始化讲师默认数据
teacher: {
sort: 0,
level: 1
},
saveBtnDisabled: false // 保存按钮是否禁用;防止表单重复提交
}
},
// 页面渲染成功
created() {
},
methods: {
saveOrUpdate() {
// 禁用保存按钮
this.saveBtnDisabled = true
if (!this.teacher.id) {
this.saveData()
} else {
this.updateData()
}
},
// 新增讲师
saveData() {
// debugger
teacherApi.save(this.teacher).then(response => {
this.$message({
type: ;success;,
message: response.message
})
this.$router.push({ path: ;/vod/teacher/list; })
})
},
// 根据id更新记录
updateData() {
}
}
}
</script>
<style scoped>
.avatar-uploader .avatar-uploader-icon {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
Overflow: hidden;
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar-uploader .avatar-uploader-icon:hover {
border-color: #409EFF;
}
.avatar-uploader img {
width: 178px;
height: 178px;
display: block;
}
</style>
src/api/vod/teacher.js
getById(id) {
return request({
url: ;${api_name}/get/${id};,
method: ;get;
})
},
methods中定义fetchDataById
// 根据id查询记录
fetchDataById(id) {
teacherApi.getById(id).then(response => {
this.teacher = response.data
})
},
// 页面渲染成功
created() {
if (this.$route.params.id) {
this.fetchDataById(this.$route.params.id)
}
},
updateById(teacher) {
return request({
url: ;${api_name}/update;,
method: ;put;,
data: teacher
})
},
methods中定义updateData
// 根据id更新记录
updateData() {
// teacher数据的获取
teacherApi.updateById(this.teacher).then(response => {
this.$message({
type: ;success;,
message: response.message
})
this.$router.push({ path: ;/vod/teacher/list; })
})
},
saveOrUpdate() {
// 禁用保存按钮
this.saveBtnDisabled = true
if (!this.teacher.id) {
this.saveData()
} else {
this.updateData()
}
},
src/api/vod/teacher.js
batchRemove(idList) {
return request({
url: ;${api_name}/batch-remove;,
method: ;delete;,
data: idList
})
},
src/views/vod/teacher/list.vue
在table组件上添加 批量删除 按钮
<!-- 工具按钮 -->
<el-card class=;operate-container; shadow=;never;>
<i class=;el-icon-tickets; style=;margin-top: 5px;></i>
<span style=;margin-top: 5px;>数据列表</span>
<el-button class=;btn-add; ;click=;add(); style=;margin-left: 10px;;>添加</el-button>
<el-button class=;btn-add; ;click=;batchRemove(); >批量删除</el-button>
</el-card>
在table组件上添加复选框
<!-- 表格 -->
<el-table
:data=;list;
border
stripe
;selection-change=;handleSelectionChange;>
<el-table-column type=;selection;/>
data定义数据
multipleSelection: []// 批量删除选中的记录列表
完善方法
// 批量删除
batchRemove() {
if (this.multipleSelection.length === 0) {
this.$message.warning(;请选择要删除的记录;;)
return
}
this.$confirm(;此操作将永久删除该记录, 是否继续?;, ;提示;, {
confirmButtonText: ;确定;,
cancelButtonText: ;取消;,
type: ;warning;
}).then(() => {
// 点击确定;远程调用ajax
// 遍历selection;将id取出放入id列表
var idList = []
this.multipleSelection.forEach(item => {
idList.push(item.id)
})
// 调用api
return teacherApi.batchRemove(idList)
}).then((response) => {
this.fetchData()
this.$message.success(response.message)
}).catch(error => {
if (error === ;cancel;) {
this.$message.info(;取消删除;)
}
})
},
// 当多选选项发生变化的时候调用
handleSelectionChange(selection) {
console.log(selection)
this.multipleSelection = selection
},
;Api(tags = ;讲师管理;)
;RestController
;RequestMapping(value=;/admin/vod/teacher;)
;CrossOrigin
public class TeacherController {
;Autowired
private TeacherService teacherService;
//查询所有讲师列表
;ApiOperation(;查询所有讲师;)
;GetMapping(;findAll;)
public Result findAll(){
/*try {
int i = 10/0;
} catch (Exception e) {
throw new GgktException(201,;出现自定义异常;);
}*/
List<Teacher> list = teacherService.list();
return Result.ok(list);
}
;DeleteMapping(;remove/{id};)
public Result remove(;PathVariable Long id){
boolean flag = teacherService.removeById(id);
if(flag){
return Result.ok(null);
}else {
return Result.fail(null);
}
}
//条件查询分页列表
;ApiOperation(value = ;获取分页列表;)
;PostMapping(;findQueryPage/{page}/{limit};)
public Result index(
;ApiParam(name = ;page;, value = ;当前页码;, required = true)
;PathVariable Long page,
;ApiParam(name = ;limit;, value = ;每页记录数;, required = true)
;PathVariable Long limit,
;ApiParam(name = ;teacherVo;, value = ;查询对象;, required = false)
;RequestBody(required = false) TeacherQueryVo teacherQueryVo) {
//创建page对象;传递当前页和每页记录数
Page<Teacher> pageParam = new Page<>(page, limit);
//获取条件值
String name = teacherQueryVo.getName();//讲师名称
Integer level = teacherQueryVo.getLevel();//讲师级别
String joinDateBegin = teacherQueryVo.getJoinDateBegin();//开始时间
String joinDateEnd = teacherQueryVo.getJoinDateEnd();//结束时间
//封装条件
QueryWrapper<Teacher> wrapper = new QueryWrapper<>();
if(!StringUtils.isEmpty(name)) {
wrapper.like(;name;,name);
}
if(!StringUtils.isEmpty(level)) {
wrapper.eq(;level;,level);
}
if(!StringUtils.isEmpty(joinDateBegin)) {
wrapper.ge(;join_date;,joinDateBegin);
}
if(!StringUtils.isEmpty(joinDateEnd)) {
wrapper.le(;join_date;,joinDateEnd);
}
//调用方法得到分页查询结果
IPage<Teacher> pageModel = teacherService.page(pageParam, wrapper);
return Result.ok(pageModel);
}
;ApiOperation(value = ;新增;)
;PostMapping(;save;)
public Result save(;RequestBody Teacher teacher) {
teacherService.save(teacher);
return Result.ok(null);
}
;ApiOperation(value = ;获取;)
;GetMapping(;get/{id};)
public Result get(;PathVariable Long id) {
Teacher teacher = teacherService.getById(id);
return Result.ok(teacher);
}
;ApiOperation(value = ;修改;)
;PutMapping(;update;)
public Result updateById(;RequestBody Teacher teacher) {
teacherService.updateById(teacher);
return Result.ok(null);
}
;ApiOperation(value = ;根据id列表删除;)
;DeleteMapping(;batchRemove;)
public Result batchRemove(;RequestBody List<Long> idList) {
teacherService.removeByIds(idList);
return Result.ok(null);
}
}