列表的批量操作组件封装 + 权限 ,如何更优雅的实现呢?Vue3
-
这个组件解决的问题?
在以往的项目当中,我从未想过要对 批量/列表数据的操作按钮做什么变动,直到最近的一次开发。
当页面功能多而复杂,整个页面会变得十分混乱,就比如,当操作按钮过多时,操作按钮的触发判断条件、权限指令、更多下拉操作等等,这使得页面十分混乱,维护起来让人头疼。
当然也会出现:多个操作弹窗、搜索条件过多、监听路由参数变化。我会在后面的随笔中记录。 -
当操作按钮过多时,如何解决这个问题
封装批量操作组件,操作按钮分明显按钮 和 更多下拉操作按钮。
将页面操作放在action.js 文件中,包含 触发判断条件、权限指令、控制显示/隐藏。 -
如何使用?
全局(main.js中)引用操作组件 BatchOperation.vue
创建页面操作按钮 actions.js 文件 -
BatchOperation.vue 全局操作按钮组件文件代码:
<template> <div> <!-- 列表顶部的批量操作按钮组件 / 表格中的操作按钮--> <el-row :gutter="10" class="mb8 mt10" type="flex" justify="center"> <slot name="default"></slot> <el-col :span="1.5" v-for="action, index in visibleAction" :key="action.command" v-show="visibleAction.length > 0"> <el-button :link="inColumn" :type="getBtnType(index)" plain :disabled="action.disabled" v-hasPermi="action.permission" @click="commandAction(action.command)">{{action.name}}</el-button> </el-col> <el-col :span="1.5" v-if="moreActionsVisible"> <el-dropdown @command="commandAction" :size="inColumn ? 'default' : 'large'" style="line-height:inherit;vertical-align: bottom;"> <el-button type="primary" plain :link="inColumn"> 更多操作<el-icon class="el-icon--right"><arrow-down /></el-icon> </el-button> <template #dropdown> <el-dropdown-menu> <div v-hasPermi="action.permission" v-for="action in moreActions" :key="action.command"> <el-dropdown-item :disabled="action.disabled" :command="action.command" > {{action.name}} </el-dropdown-item> </div> </el-dropdown-menu> </template> </el-dropdown> </el-col> <slot name="rightToolbar"></slot> </el-row> </div> </template> <script setup> import take from 'lodash/take' import takeRight from 'lodash/takeRight' import mapValues from 'lodash/mapValues' import pickBy from 'lodash/pickBy' import values from 'lodash/values' import sortBy from 'lodash/sortBy' // button type const btnType = ['primary', 'success', 'warning', 'danger', 'info', 'default'] // props const getBtnType =(index)=>{ const indx = index % btnType.length return btnType[indx] } // actions command const emits = defineEmits() // props const props = defineProps(['actions','visibleCount','inColumn']) // 明显按钮 默认显示前五个按钮; 如果是在 数据行操作只显示 1 个 const MAX = computed(()=>{ const count = props.inColumn ? 1 : 5 return props.visibleCount === undefined ? count : props.visibleCount }) // 将 key 作为 command。 hiddenInColunm 在表中隐藏 onlyInColunm 只在表格列中显示 hidden 都不显示 const operations = computed(()=>{ let actions = pickBy(props.actions, a =>(props.inColumn ? (!a.hiddenInColunm) : !a.onlyInColunm) && !a.hidden) actions = mapValues(actions,(value,key)=>{ value.command = key return value }) // 将可用功能优先排序 return sortBy(values(actions), (a)=>a.disabled) }) // 明显按钮 const visibleAction = computed(()=>{ return take(operations.value, MAX.value) }) // 更多操作下拉按钮 const moreActions = computed(()=>{ return takeRight(operations.value, operations.value.length - MAX.value) }) // 是否显示更多按钮 const moreActionsVisible = computed(()=>MAX.value == 0 || operations.value.length > visibleAction.value.length) // 点击更多操作里的按钮 const commandAction =(command)=>{ emits(command) } </script>
-
actions.js 页面操作,举个例子:
// single:批量勾选 false 单条数据,true 非单条数据 // multiple:批量勾选 false 已勾选 true 未勾选 // row:单行数据。当 single 为 false 时, row 也须有值 export default function (single, multiple, row) { return { 'create': { name: "新增",// 按钮名称 permission: ['bless:product:permissionAdd'],// 权限字符 disabled: false, // 是否可点击 hiddenInColunm: true // 在表格列中隐藏 }, 'edit': { name: "修改", permission: ['bless:product:permissionEdit'], // 单行 或者 row 存在且符合( ... )中的条件时 disabled: single || ( row ? ( row.status !=0 && row.status !=3 ) : true), onlyInColunm: true // 仅在列表中显示 }, 'delete': { name: "删除", permission: ['bless:product:permissionRemove'], disabled: multiple, }, 'search': { name: "查询", permission: ['bless:product:permissionPage'], disabled: false, hidden: true // 隐藏 } } }
-
页面使用操作按钮:UI 组件:element-plus
<template> <!-- v-hasPermi 权限指令 详见 若依--自定义指令--> <div v-hasPermi="actions['search'].permission"> <!-- 批量操作 --> <BatchOperation :actions="actions" @create="handleCreate" @delete="handleDelete" > <!-- 刷新按钮 --> <template #rightToolbar> <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> </template> </BatchOperation> <!-- 列表 --> <el-table :data="list" row-key="productId" @selection-change="handleSelectionChange"> <!-- 勾选框 --> <el-table-column type="selection" width="55" align="center" fixed="left" /> ...(这里就是列表展示的数据) <!-- 单行操作按钮 --> <el-table-column label="操作" fixed="right" header-align="center" width="150px"> <template #default="{row}"> <BatchOperation :inColumn="true" :actions="initAction(false, false, row)" @edit="handleEdit(row)" @delete="handleDelete(row.productId)" ></BatchOperation> </template> </el-table-column> </el-table> </div> </template> <script setup name="ProductIndex"> import { getPages, remove } from '@/api/product' import initAction from './components/actions' // 勾选 const multipleSelection = ref([]) // ids // 非单个禁用 const single = computed(() => multipleSelection.value.length != 1) // 非多个禁用 const multiple = computed(() => !multipleSelection.value.length) // 当前选中 const selectedRow = computed(() => { if (multipleSelection.value.length == 1) { return list.value.find(z => z.productId == multipleSelection.value[0]) } return null }) // 批量操作按钮 const actions = computed(()=>initAction(single.value, multiple.value, selectedRow.value)) // 批量勾选触发 const handleSelectionChange = (val) => { multipleSelection.value = val.map(z => z.productId) } // 点击 新增 const handleCreate =()=>{ router.push('/product/create') } // 点击 修改 const handleEdit =(row)=>{ const current = row || selectedRow.value router.push('/product/edit/' + current.productId) } // 批量删除 const handleDelete = (id) => { proxy.$modal.confirm('确定删除?') .then(() => { const ids = id || multipleSelection.value remove(ids).then(res => { if (res.code == 200) { proxy.$modal.msgSuccess("操作成功") getList() } else { proxy.$modal.msgError(res.msg || "请求发生错误,请稍后重试") } }) }) .catch(() => { proxy.$modal.msg("已取消") }) } // 获取列表数据 const getList = () => { proxy.$modal.loading("加载中...") // **这里 searchRef 会在后面的随笔中说明** const { dateRange, ...search } = searchRef.value.form const query = { ...pager.value, ...search } const data = dateRange ? proxy.addDateRange(query, dateRange) : query getPages(data).then(response => { list.value = response.data.rows; total.value = parseInt(response.data.total); expandRowKeys.value = [] }).finally(() => { proxy.$modal.closeLoading(); }); } </script>
作者:胡倩倩0903
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
分类:
vue
posted on 2023-05-08 09:27 kitty20180903suzhou 阅读(172) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY