✔ 完成角色信息的增删改查功能。
读取角色信息
- 封装读取角色信息的接口,
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, }) }
|
- 在页面中调用接口获取数据,
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 } }, created() { this.getRoleList() }, methods: { async getRoleList() { const { rows, total } = await getRoleList(this.query) this.list = rows this.total = total } } }
|
- 绑定数据到表格。
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 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>
|
- 监听
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() } } }
|
- 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 { loading: false } }, methods: { async getRoleList() { this.loading = true const { rows, total } = await getRoleList(this.query) this.loading = false this.list = rows this.total = total }, } }
|
1 2
| <el-card v-loading="loading"></el-card>
|
- 解决序号的问题。
1 2 3
|
<el-table-column :index="indexFn"></el-table-column>
|
1 2 3 4 5
| indexFn(index) { return index + 1 + (this.query.page - 1) * this.query.pagesize }
|
- 改成中文展示,
main.js
。
删除角色功能
目标
实现删除角色的功能。
内容
- 封装删除角色的接口,
api/role.js
。
1 2 3 4 5 6 7
| export function deleteRole(id) { return request({ url: `/sys/role/${id}`, method: 'delete', }) }
|
- 给删除按钮注册事件并调用方法,
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 2 3 4 5 6 7 8 9 10 11 12 13 14
| async deleteRole(id) { try { await this.$confirm('确认删除该角色吗') await deleteRole(id) if (this.list.length === 1 && this.query.page > 1) { this.query.page-- } this.getRoleList() this.$message.success('删除角色成功') } catch (error) { console.log(error) } }
|
新增角色功能
目标
实现新增角色功能。
内容
- 封装新增角色的接口,
api/role.js
。
1 2 3 4 5 6 7 8
| export function addRole(data) { return request({ url: '/sys/role', data, method: 'post', }) }
|
- 准备新增角色的按钮,
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 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 2 3 4 5 6 7 8 9 10 11
| export default { name: 'Role', data() { return { 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 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 { roleForm: { name: '', description: '', state: 0 }, 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"> <el-form label-width="120px" :model="roleForm" :rules="rules"> <el-form-item label="角色名称" prop="name"> <el-input v-model="roleForm.name" style="width:300px" size="mini" /> </el-form-item> <el-form-item label="启用" prop="state"> <el-switch v-model="roleForm.state" :active-value="1" :inactive-value="0" size="mini" /> </el-form-item> <el-form-item label="角色描述" prop="description"> <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 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 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 2
| <el-dialog width="500px" title="新增角色" :visible.sync="showRoleDialog" @close="cancelRoleDialog"></el-dialog>
|
1
| <el-button size="mini" @click="cancelRoleDialog">取消</el-button>
|
编辑角色功能
目标
实现编辑角色的功能。
封装编辑接口
- 封装编辑角色的接口,
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', }) }
|
- 获取数据之后,对每行数据添加表示编辑状态的标识,
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 this.list.forEach(item => (item.isEdit = false)) }
|
- 点击编辑按钮时,将当前行的标记 isEdit 设置为 true。
1
| <el-button size="small" type="text" @click="btnEditRow(row)"> 编辑 </el-button>
|
1 2 3
| btnEditRow(row) { row.isEdit = true }
|
- 表格列中根据当前的 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" /> <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> <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> <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> <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 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 this.list.forEach(item => this.$set(item, 'isEdit', false)) }
|
行内缓存功能
为什么要做数据缓存?因为编辑时,可以取消滚到之前的状态,所以编辑时的数据是临时的。
- 初始化缓存数据。
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 this.list.forEach(item => { this.$set(item, 'isEdit', false) this.$set(item, 'editRow', { name: item.name, state: item.state, description: item.description }) }) }
|
- 将缓存数据双向绑定到表单。
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 }"> <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}"> <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 }"> <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 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('更新角色成功') Object.assign(row, { ...row.editRow, isEdit: false }) } else { this.$message.warning('角色和描述不能为空') } }
|
- 每次点击编辑都显示初始的行内数据。
重现步骤:点击编辑按钮 => 修改角色 => 取消 => 再次点击编辑按钮。
1 2 3 4 5 6 7
| btnEditRow(row) { row.isEdit = true row.editRow.name = row.name row.editRow.state = row.state row.editRow.description = row.description }
|