1. 前端框架 23
1.1 vue-element-admin
vue-element-admin是基于element-ui 的一套后台管理系统集成方案。
功能:https://panjiachen.github.io/vue-element-admin-site/zh/guide/#功能
GitHub地址:https://github.com/PanJiaChen/vue-element-admin
项目在线预览:https://panjiachen.gitee.io/vue-element-admin
1.2 vue-admin-template 23
1.2.1 简介 23
vue-admin-template是基于vue-element-admin的一套后台管理系统基础模板(最少精简版),可作为模板进行二次开发。
GitHub地址:https://github.com/PanJiaChen/vue-admin-template
建议:你可以在 `vue-admin-template` 的基础上进行二次开发,把 `vue-element-admin`当做工具箱,想要什么功能或者组件就去 `vue-element-admin` 那里复制过来。
1.2.2 安装 23
解压 资料在E:\java学习\云尚办公\资料\资料\4-vue模板中
并且重命名为guigu-oa-admin
将解压后的文件复制到工作区中(复制到E:\java学习\云尚办公\vscode\guigu-oa)
根据配置文件下载相关依赖packagejson
在guigu-oa-admin终端输入命令: npm install
依赖下载成功后启动项目
在guigu-oa-admin终端输入命令: npm run dev
启动成功
浏览器输入http://localhost:9528/进行访问
1.3源码目录结构 23
了解即可
|-dist 生产环境打包生成的打包项目
|-mock 使用mockjs来mock接口
|-public 包含会被自动打包到项目根路径的文件夹
|-index.html 唯一的页面
|-src
|-api 包含接口请求函数模块
|-table.js 表格列表mock数据接口的请求函数
|-user.js 用户登陆相关mock数据接口的请求函数
|-assets 组件中需要使用的公用资源
|-404_images 404页面的图片
|-components 非路由组件
|-SvgIcon svg图标组件
|-Breadcrumb 面包屑组件(头部水平方向的层级组件)
|-Hamburger 用来点击切换左侧菜单导航的图标组件
|-icons
|-svg 包含一些svg图片文件
|-index.js 全局注册SvgIcon组件,加载所有svg图片并暴露所有svg文件名的数组
|-layout
|-components 组成整体布局的一些子组件
|-mixin 组件中可复用的代码
|-index.vue 后台管理的整体界面布局组件
|-router
|-index.js 路由器
|-store
|-modules
|-app.js 管理应用相关数据
|-settings.js 管理设置相关数据
|-user.js 管理后台登陆用户相关数据
|-getters.js 提供子模块相关数据的getters计算属性
|-index.js vuex的store
|-styles
|-xxx.scss 项目组件需要使用的一些样式(使用scss)
|-utils 一些工具函数
|-auth.js 操作登陆用户的token cookie
|-get-page-title.js 得到要显示的网页title
|-request.js axios二次封装的模块
|-validate.js 检验相关工具函数
|-index.js 日期和请求参数处理相关工具函数
|-views 路由组件文件夹
|-dashboard 首页
|-login 登陆
|-App.vue 应用根组件
|-main.js 入口js
|-permission.js 使用全局守卫实现路由权限控制的模块
|-settings.js 包含应用设置信息的模块
|-.env.development 指定了开发环境的代理服务器前缀路径
|-.env.production 指定了生产环境的代理服务器前缀路径
|-.eslintignore eslint的忽略配置
|-.eslintrc.js eslint的检查配置
|-.gitignore git的忽略配置
|-.npmrc 指定npm的淘宝镜像和sass的下载地址
|-babel.config.js babel的配置
|-jsconfig.json 用于vscode引入路径提示的配置
|-package.json 当前项目包信息
|-package-lock.json 当前项目依赖的第三方包的精确信息
|-vue.config.js webpack相关配置(如: 代理服务器)
2. 实现登录&退出登录 24
登录
获取用户信息
2.1 修改访问路径 24
2.1.1 修改方式一
修改前端项目的.env.development
2.1.2 修改方式二 修改vue.config.js 24
修改vue.config.js文件
注释掉mock接口配置
配置代理转发请求到目标接口
// before: require('./mock/mock-server.js')
proxy: {
'/dev-api': { // 匹配所有以 '/dev-api'开头的请求路径
target: 'http://localhost:8800',
changeOrigin: true, // 支持跨域
pathRewrite: { // 重写路径: 去掉路径中开头的'/dev-api'
'^/dev-api': ''
}
}
}
解释图解
2.2 在后端创建登录相关接口返回mock相同数据 24
这里做个解释,我们这个登陆呢是为了调试借楼写的,并不是真正的登录实现,这个登录仅仅是根据前端需要返回什么样的数据,我们就返回什么样的数据的假登录,因为我们根本没有做验证,只是为了方便测试
在service-oa模块
IndexController
package com.atguigu.auth.controller;
import com.atguigu.common.result.Result;
import io.swagger.annotations.Api;
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;
import java.util.HashMap;
import java.util.Map;
// 实现登录&退出登录 24
@Api(tags = "后台登录管理")
@RestController
@RequestMapping("/admin/system/index")
public class IndexController {
/**
* 登录 24
* @return
*/
@PostMapping("login")
public Result login() {
Map<String, Object> map = new HashMap<>();
map.put("token","admin-token");
return Result.ok(map);
}
/**
* 获取用户信息 24
* @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();
}
}
2.3 修改前端 24
2.3.1 修改接口名称 24
可以看到前端中的接口名称和我们后端写的不一样,需要修改
找到前端,将user.js中的接口路径做修改为本地路径
修改后
2.3.2 修改状态码 24
可以看到前端的状态码是20000,而后端我们定义的是200
找到request.js
修改
2.4 测试 24
重新启动前端
启动后端
登录成功
3. 角色列表 25
3.1 修改路由 25
(这个路由的意思就是侧边的类似菜单的选项)
在前端router.js中添加路由
{
path: '/system',
component: Layout,
meta: {
title: '系统管理',
icon: 'el-icon-s-tools'
},
alwaysShow: true,
children: [
{
path: 'sysRole',
component: () => import('@/views/system/sysRole/list'),
meta: {
title: '角色管理',
icon: 'el-icon-s-help'
},
}
]
},
根据角色路由创建页面
3.2 定义api 25
在api文件夹中创建js文件,定义接口信息
创建文件 src/api/system/sysRole.js
sysRole.js
import request from '@/utils/request'
const api_name = '/admin/system/sysRole'
export default {
//角色列表-条件分页查询 25
getPageList(current,limit,searchObj) {
return request({
url: `${api_name}/${current}/${limit}`,
method: 'get',
//如果普通对象参数写法 params:对象参数名称
//如果使用json格式传递,data:对象参数名称
params:searchObj
})
}
}
在api接口定义完成后,我们接下来在页面引入定义接口的js文件,调用接口通过axios实现功能
3.3 初始化vue组件 25
在views文件夹中创建页面,在页面引入定义接口的js文件,调用接口通过axios实现功能
list.vue
<template>
<div class="app-container">
<!--查询表单 26-->
<div class="search-div">
<el-form label-width="70px" size="small">
<el-row>
<el-col :span="24">
<el-form-item label="角色名称">
<el-input style="width: 100%" v-model="searchObj.roleName" placeholder="角色名称"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row style="display:flex">
<el-button type="primary" icon="el-icon-search" size="mini" :loading="loading" @click="fetchData()">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetData">重置</el-button>
</el-row>
</el-form>
</div>
<!-- 表格 26-->
<el-table
v-loading="listLoading"
:data="list"
stripe
border
style="width: 100%;margin-top: 10px;"
@selection-change="handleSelectionChange">
<el-table-column type="selection"/>
<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="roleName" label="角色名称" />
<el-table-column prop="roleCode" label="角色编码" />
<el-table-column prop="createTime" label="创建时间" width="160"/>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" size="mini" @click="edit(scope.row.id)" title="修改"/>
<el-button type="danger" icon="el-icon-delete" size="mini" @click="removeDataById(scope.row.id)" title="删除"/>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 26-->
<el-pagination
:current-page="page"
:total="total"
:page-size="limit"
style="padding: 30px 0; text-align: center;"
layout="total, prev, pager, next, jumper"
@current-change="fetchData"
/>
</div>
</template>
<script>
import api from '@/api/system/sysRole'
export default {
// 定义数据模型 26
//初始值 26
data() {
return {
list:[],//角色列表
page:1,//当前页
limit:1,//每页显示记录数
total:0,//总记录数
searchObj:{},//条件对象
}
},
// 页面渲染成功后获取数据
created() {
this.fetchData()
},
// 定义方法
methods: {//操作方法 26
fetchData(current=1) {
//条件分页查询 26
this.page = current
api.getPageList(this.page,this.limit,this.searchObj)
.then(response => {
this.list = response.data.records
this.total = response.data.total
})
}
}
}
</script>
3.4 测试 26
浏览器输入 http://localhost:9529/,成功
4. 删除角色 27
4.1定义api 27
sysRole.js
//角色删除 27
removeById(id) {
return request({
url: `${api_name}/remove/${id}`,
method: 'delete'
})
}
4.2 实现功能 27
list.vue
//删除 27
removeDataById(id) {
this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//调用
return api.removeById(id)
}).then(response => {
//刷新页面
this.fetchData()
//提示信息
this.$message.success(response.message || '删除成功')
})
}
4.3 测试 27
5. 角色添加 28
5.1 添加按钮 28
src/views/system/sysRole
list.vue
<!-- 工具条 -->
<div class="tools-div">
<el-button type="success" icon="el-icon-plus" size="mini" @click="add">添 加</el-button>
</div>
5.2 定义api 28
src/api/system/sysRole.js
sysRole.js
//角色添加 28
saveRole(role) {
return request({
url: `${api_name}/save`,
method: 'post',
data:role
})
}
5.3 实现功能 28
5.3.1 定义弹出层
src/views/system/sysRole/list.vue
表格最下面添加弹出层
list.vue
<el-dialog title="添加/修改" :visible.sync="dialogVisible" width="40%" >
<el-form ref="dataForm" :model="sysRole" label-width="150px" size="small" style="padding-right: 40px;">
<el-form-item label="角色名称">
<el-input v-model="sysRole.roleName"/>
</el-form-item>
<el-form-item label="角色编码">
<el-input v-model="sysRole.roleCode"/>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false" size="small" icon="el-icon-refresh-right">取 消</el-button>
<el-button type="primary" icon="el-icon-check" @click="saveOrUpdate()" size="small">确 定</el-button>
</span>
</el-dialog>
5.3.2 功能实现 28
src/views/system/sysRole/list.vue
list.vue
//添加或者修改 28
saveOrUpdate() {
//根据id判断
if (!this.sysRole.id) {//添加
this.save()
} else {//修改
this.update()
}
},
save() { //添加 28
api.saveRole(this.sysRole)
.then(response => {
//提示
this.$message.success(response.message || '操作成功')
//关闭弹框
this.dialogVisible = false
//刷新页面
this.fetchData()
})
},
5.4 测试
6. 修改角色 29
6.1 定义api
src/api/system/sysRole.js
sysRole.js
//根据id查询数据 29
getById(id) {
return request({
url: `${api_name}/get/${id}`,
method: 'get'
})
},
//修改 29
updateById(role) {
return request({
url: `${api_name}/update`,
method: 'put',
data: role
})
}
6.2 功能实现 29
src/views/system/sysRole/list.vue
list.vue
//点击修改,弹出框,根据id查询数据显示 29
edit(id) {
//弹出框
this.dialogVisible = true
//根据id查询
this.fetchDataById(id)
},
//根据id查询 29
fetchDataById(id) {
api.getById(id)
.then(response => {
this.sysRole = response.data
})
},
update() { //修改 29
api.updateById(this.sysRole)
.then(response => {
//提示
this.$message.success(response.message || '操作成功')
//关闭弹框
this.dialogVisible = false
//刷新页面
this.fetchData()
})
}
6.3 测试 29
7. 角色批量删除 30
7.1 定义api 30
src/api/system/sysRole.js
sysRole.js
//批量删除 30
batchRemove(idList) {
return request({
url: `${api_name}/batchRemove`,
method: 'delete',
data: idList
})
}
7.2 功能实现 30
src/views/system/sysRole/list.vue
7.2.1 在table组件上添加 批量删除 按钮 30
list.vue
<!-- 工具条 -->
<div class="tools-div">
<el-button type="success" icon="el-icon-plus" size="mini" @click="add">添 加</el-button>
<el-button class="btn-add" size="mini" @click="batchRemove()" >批量删除</el-button>
</div>
7.2.2 功能实现 30
src/views/system/sysRole/list.vue
list.vue
//选择复选框,把复选框所在行内容传递 30
handleSelectionChange(selection) {
this.selections = selection
console.log(this.selections)
},
//批量删除 30
batchRemove() {
//判断
if(this.selections.length == 0) {
this.$message.warning('请选择要删除的记录!')
return
}
this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// [1,2,3]
var idList = []
//选择复选框数据在数组里面 this.selections
this.selections.forEach(item => {
var id = item.id
idList.push(id)
});
return api.batchRemove(idList)
}).then(response => {
this.$message.success(response.message)
this.fetchData()
})
}