危险

为之则易,不为则难

0%

05_人资后台

✔ 完成角色信息的增删改查功能。

读取角色信息

  1. 封装读取角色信息的接口,api/role.js
1
2
3
4
5
6
7
8
import request from '@/utils/request'
// 获取角色列表
export function getRoleList(params) {
return request({
url: '/sys/role',
params,
})
}
  1. 在页面中调用接口获取数据,views/role/index.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import {
getRoleList
} from '@/api/role'
export default {
name: 'Role',
data() {
return {
list: [],
query: {
page: 1,
pagesize: 10
},
total: 0 // total,后续做分页用
}
},
created() {
this.getRoleList()
},
methods: {
async getRoleList() {
const {
rows,
total
} = await getRoleList(this.query)
this.list = rows
this.total = total
}
}
}
  1. 绑定数据到表格。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<el-card>
<el-table border :data="list">
<el-table-column align="center" type="index" label="序号" width="120" />
<el-table-column align="center" prop="name" label="角色" width="240" />
<el-table-column align="center" prop="state" label="状态" width="240">
<template v-slot="{row}">
<span>{{ row.state === 1 ? '已启用' : row.state === 0 ? '未启用' : '未知' }}</span>
</template>
</el-table-column>
<el-table-column align="center" prop="description" label="描述" />
<el-table-column align="center" label="操作">
<el-button size="small" type="text">分配权限</el-button>
<el-button size="small" type="text">编辑</el-button>
<el-button size="small" type="text">删除</el-button>
</el-table-column>
</el-table>
</el-card>

处理分页数据

  1. 绑定分页数据。
1
2
3
4
<!-- 放置分页组件 -->
<el-row type="flex" align="middle" justify="center" style="height: 60px">
<el-pagination :page-sizes="[2, 4, 6, 8, 10]" layout="total, sizes, prev, pager, next, jumper" :page-size="query.pagesize" :current-page="query.page" :total="total" />
</el-row>
  1. 监听 el-pagination 组件的 @current-change@size-change 事件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export default {
name: 'Role',
// ...
methods: {
// ...
changeCurrent(page) {
this.query.page = page
this.getRoleList()
},
changeSize(size) {
// 每页的条数变化后,当前页不一定就是当前页了
this.query.page = 1
this.query.pagesize = size
this.getRoleList()
}
}
}
  1. loading 提示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
export default {
name: 'Role',
data() {
return {
// ...
// #1
loading: false
}
},
// ...
methods: {
async getRoleList() {
// #2
this.loading = true
const {
rows,
total
} = await getRoleList(this.query)
// #3
this.loading = false
this.list = rows
this.total = total
},
// ...
}
}
1
2
<!-- #4 -->
<el-card v-loading="loading"></el-card>
  1. 解决序号的问题。
1
2
3
<!-- 表示从 500 开始 -->
<!-- <el-table-column :index="500"></el-table-column> -->
<el-table-column :index="indexFn"></el-table-column>
1
2
3
4
5
indexFn(index) {
// index + 1 当前页的序号,默认就是这个,展示是 0、1、2 这样
// (页码 - 1) * 每页展示多少条
return index + 1 + (this.query.page - 1) * this.query.pagesize
}
  1. 改成中文展示,main.js
1
Vue.use(ElementUI)

删除角色功能

目标

实现删除角色的功能。

内容

  1. 封装删除角色的接口,api/role.js
1
2
3
4
5
6
7
// 删除角色
export function deleteRole(id) {
return request({
url: `/sys/role/${id}`,
method: 'delete',
})
}
  1. 给删除按钮注册事件并调用方法,views/role/index.vue
1
2
3
4
5
6
<!-- 作用域插槽 -->
<template v-slot="{ row }">
<el-button size="small" type="text">分配权限</el-button>
<el-button size="small" type="text">编辑</el-button>
<el-button size="small" type="text" @click="deleteRole(row.id)">删除</el-button>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import {
deleteRole
} from '@/api/role'
export default {
name: 'Role',
// ...
methods: {
// ...
async deleteRole(id) {
try {
// 只有点击了确定才能进入到下方
await this.$confirm('确认删除该角色吗')
// 调用删除接口
await deleteRole(id)
// 重新加载数据
this.getRoleList()
// 提示
this.$message.success('删除角色成功')
} catch (error) {
console.log(error)
}
}
}
}
  1. 删除数据的边界值处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
async deleteRole(id) {
try {
await this.$confirm('确认删除该角色吗')
await deleteRole(id)
// #mark
if (this.list.length === 1 && this.query.page > 1) {
this.query.page--
}
this.getRoleList()
this.$message.success('删除角色成功')
} catch (error) {
console.log(error)
}
}

新增角色功能

目标

实现新增角色功能。

内容

  1. 封装新增角色的接口,api/role.js
1
2
3
4
5
6
7
8
// 新增角色
export function addRole(data) {
return request({
url: '/sys/role',
data,
method: 'post',
})
}
  1. 准备新增角色的按钮,views/role/index.vue
1
2
3
<el-row type="flex" align="middle" justify="end" style="height: 60px">
<el-button type="primary" size="small">新增角色</el-button>
</el-row>
  1. 准备新增角色的弹框。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<el-dialog width="500px" title="新增角色" visible>
<el-form label-width="120px">
<el-form-item label="角色名称">
<el-input style="width:300px" size="mini" />
</el-form-item>
<el-form-item label="启用">
<el-switch :active-value="1" :inactive-value="0" size="mini" />
</el-form-item>
<el-form-item label="角色描述">
<el-input type="textarea" :rows="3" style="width:300px" size="mini" />
</el-form-item>
<el-form-item>
<el-row type="flex" justify="center">
<el-col :span="12">
<el-button type="primary" size="mini">确定</el-button>
<el-button size="mini">取消</el-button>
</el-col>
</el-row>
</el-form-item>
</el-form>
</el-dialog>
  1. 点击按钮控制弹框的显示/隐藏。
1
2
3
4
5
6
7
8
9
10
11
export default {
name: 'Role',
data() {
return {
// ...
// #1
showRoleDialog: false
}
}
// ...
}
1
<el-dialog width="500px" title="新增角色" :visible.sync="showRoleDialog"></el-dialog>
1
<el-button type="primary" size="small" @click="showRoleDialog = true">新增角色</el-button>
  1. 收集和校验表单数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
export default {
name: 'Role',
data() {
return {
// ...
// #1
roleForm: {
name: '',
description: '',
state: 0 // 0 关闭
},
// #2
rules: {
name: [{
required: true,
message: '角色名称不能为空',
trigger: 'blur'
}],
description: [{
required: true,
message: '角色描述不能为空',
trigger: 'blur'
}]
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<el-dialog width="500px" title="新增角色" :visible.sync="showRoleDialog">
<!-- #3 -->
<el-form label-width="120px" :model="roleForm" :rules="rules">
<!-- #4 prop -->
<el-form-item label="角色名称" prop="name">
<!-- #5 -->
<el-input v-model="roleForm.name" style="width:300px" size="mini" />
</el-form-item>
<!-- #6 重置表单数据,需要 prop 属性 -->
<el-form-item label="启用" prop="state">
<!-- #7 -->
<el-switch v-model="roleForm.state" :active-value="1" :inactive-value="0" size="mini" />
</el-form-item>
<!-- #8 -->
<el-form-item label="角色描述" prop="description">
<!-- #9 -->
<el-input v-model="roleForm.description" type="textarea" :rows="3" style="width:300px" size="mini" />
</el-form-item>
<el-form-item>
<el-row type="flex" justify="center">
<el-col :span="12">
<el-button type="primary" size="mini">确定</el-button>
<el-button size="mini">取消</el-button>
</el-col>
</el-row>
</el-form-item>
</el-form>
</el-dialog>
  1. 点击按钮新增角色。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
export default {
name: 'Role',
// ...
methods: {
// ...
async btnOK() {
try {
// 只有校验通过的情况下,才会执行 await 的下方内容
await this.$refs.roleForm.validate()
// 新增业务
await addRole(this.roleForm)
this.getRoleList()
this.$message.success('操作成功')
this.cancelRoleDialog()
} catch (error) {
console.log(error)
}
},
cancelRoleDialog() {
this.showRoleDialog = false
this.$refs.roleForm.resetFields()
}
}
}
  1. 处理关闭弹框。
1
2
<!-- 给弹层绑定 @close 事件 -->
<el-dialog width="500px" title="新增角色" :visible.sync="showRoleDialog" @close="cancelRoleDialog"></el-dialog>
1
<el-button size="mini" @click="cancelRoleDialog">取消</el-button>

编辑角色功能

目标

实现编辑角色的功能。

封装编辑接口

  1. 封装编辑角色的接口, api/role.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 获取角色详情
export function getRoleDetail(id) {
return request({
url: `/sys/role/${id}`,
})
}
// 修改角色
export function updateRole(data) {
return request({
url: `/sys/role/${data.id}`,
data,
method: 'put',
})
}
  1. 获取数据之后,对每行数据添加表示编辑状态的标识,src/views/role/index.vue
1
2
3
4
5
6
7
8
9
10
11
12
async getRoleList() {
this.loading = true
const {
rows,
total
} = await getRoleList(this.query)
this.loading = false
this.list = rows
this.total = total
// mark
this.list.forEach(item => (item.isEdit = false))
}
  1. 点击编辑按钮时,将当前行的标记 isEdit 设置为 true。
1
<el-button size="small" type="text" @click="btnEditRow(row)"> 编辑 </el-button>
1
2
3
btnEditRow(row) {
row.isEdit = true
}
  1. 表格列中根据当前的 isEdit 标记渲染对应的内容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<el-table border :data="list">
<el-table-column align="center" type="index" label="序号" width="120" :index="indexFn" />
<!-- #1 -->
<el-table-column align="center" label="角色" width="240">
<template v-slot="{ row }">
<el-input v-if="row.isEdit" size="mini" />
<span v-else>{{ row.name }}</span>
</template>
</el-table-column>
<!-- #2 -->
<el-table-column align="center" label="状态" width="240">
<template v-slot="{row}">
<el-switch v-if="row.isEdit" />
<span v-else>{{ row.state === 1 ? '已启用' : row.state === 0 ? '未启用' : '未知' }}</span>
</template>
</el-table-column>
<!-- #3 -->
<el-table-column align="center" label="描述">
<template v-slot="{ row }">
<el-input v-if="row.isEdit" type="textarea" />
<span v-else>{{ row.description }}</span>
</template>
</el-table-column>
<!-- #4 -->
<el-table-column align="center" label="操作">
<template v-slot="{ row }">
<template v-if="row.isEdit">
<el-button type="primary" size="mini">确定</el-button>
<el-button size="mini">取消</el-button>
</template>
<template v-else>
<el-button size="small" type="text">分配权限</el-button>
<el-button size="small" type="text" @click="btnEditRow(row)">编辑</el-button>
<el-button size="small" type="text" @click="deleteRole(row.id)">删除</el-button>
</template>
</template>
</el-table-column>
</el-table>
  1. 问题:并没有显示对应的结构?
1
2
3
4
5
6
7
8
9
10
11
12
async getRoleList() {
this.loading = true
const {
rows,
total
} = await getRoleList(this.query)
this.loading = false
this.list = rows
this.total = total
// mark
this.list.forEach(item => this.$set(item, 'isEdit', false))
}

行内缓存功能

为什么要做数据缓存?因为编辑时,可以取消滚到之前的状态,所以编辑时的数据是临时的。

  1. 初始化缓存数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
async getRoleList() {
this.loading = true
const {
rows,
total
} = await getRoleList(this.query)
this.loading = false
this.list = rows
this.total = total
// mark
this.list.forEach(item => {
this.$set(item, 'isEdit', false)
this.$set(item, 'editRow', {
name: item.name,
state: item.state,
description: item.description
})
})
}
  1. 将缓存数据双向绑定到表单。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<el-table border :data="list">
<el-table-column align="center" type="index" label="序号" width="120" :index="indexFn" />
<el-table-column align="center" label="角色" width="240">
<template v-slot="{ row }">
<!-- #1 -->
<el-input v-if="row.isEdit" v-model="row.editRow.name" size="mini" />
<span v-else>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="状态" width="240">
<template v-slot="{row}">
<!-- #2 -->
<el-switch v-if="row.isEdit" v-model="row.editRow.state" :active-value="1" :inactive-value="0" />
<span v-else>{{ row.state === 1 ? '已启用' : row.state === 0 ? '未启用' : '未知' }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="描述">
<template v-slot="{ row }">
<!-- #3 -->
<el-input v-if="row.isEdit" v-model="row.editRow.description" size="mini" type="textarea" />
<span v-else>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="操作">
<template v-slot="{ row }">
<template v-if="row.isEdit">
<el-button type="primary" size="mini" @click="btnEditOK(row)">确定</el-button>
<el-button size="mini" @click="row.isEdit = false">取消</el-button>
</template>
<template v-else>
<el-button size="small" type="text">分配权限</el-button>
<el-button size="small" type="text" @click="btnEditRow(row)">编辑</el-button>
<el-button size="small" type="text" @click="deleteRole(row.id)">删除</el-button>
</template>
</template>
</el-table-column>
</el-table>
  1. 点击确定按钮时更新数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
async btnEditOK(row) {
if (row.editRow.name && row.editRow.description) {
// 下一步操作
await updateRole({
...row.editRow,
id: row.id
})
// 更新成功
this.$message.success('更新角色成功')
// row.name = row.editRow.name
// row.state = row.editRow.state
// row.description = row.editRow.description
// row.isEdit = false
Object.assign(row, {
...row.editRow,
isEdit: false
})
} else {
this.$message.warning('角色和描述不能为空')
}
}
  1. 每次点击编辑都显示初始的行内数据。

重现步骤:点击编辑按钮 => 修改角色 => 取消 => 再次点击编辑按钮。

1
2
3
4
5
6
7
btnEditRow(row) {
row.isEdit = true
// #mark
row.editRow.name = row.name
row.editRow.state = row.state
row.editRow.description = row.description
}