<script lang="ts" setup name="FunctionPerm"> import type { Ref } from 'vue' import { Switch } from '@element-plus/icons-vue' import { ElButton, ElDialog, ElMessage } from 'element-plus' import type { FormInstance } from 'element-plus' import type { ResourceInfo } from '../resource/resource_interface' import type { RoleInfo } from './role_interface' import { funcAuthor } from '@/api/system/role' import { getResourceListByRole } from '@/api/system/resource' import { getShowItem, toTreeList } from '@/utils/structure' // ----------------------- 以下是字段定义 emits props --------------------- const emits = defineEmits(['closeRefresh']) // 对话框是否显示 const dialogVisible = ref(false) // 显示标题-角色名称 const roleName = ref('功能权限') // 角色id const roleId = ref('') // 树列表配置项 const defaultProps = { label: 'name', children: 'children', } const filterText = ref('') // 所有资源id const resourceIds = ref([]) // 资源树列表数据 const treeList = ref([]) // 默认展开项 const defaultExpanded: Ref<string[]> = ref([]) // 默认选中项 const defaultChecked: Ref<string[]> = ref([]) // 树展开状态 const treeExpand = ref(false) // 全选 const nodeCheckedAll = ref(false) // 父子联动 const treeCheckStrictly = ref(false) // 保存按钮加载状态 const btnLoading = ref(false) // 列表加载状态 const loading = ref(false) const tree = ref() // ---------------表单提交-------------------------------- // 表单对象 const dataFormRef = ref<FormInstance>() // 提交表单 function submitForm() { const ids: string[] = tree.value.getCheckedKeys() btnLoading.value = true funcAuthor(roleId.value, ids).then((res) => { ElMessage.success('权限配置成功') btnLoading.value = false dialogClose() }).catch((_) => { // 异常情况,loading置为false btnLoading.value = false }) } // 获取当前角色的功能权限 function fetchResourceTree(roleid: string) { loading.value = true getResourceListByRole(roleid).then((response) => { if (response.data) { resourceIds.value = response.data.map((item: { id: string }) => item.id) treeList.value = toTreeList(response.data) const temp = getShowItem(response.data) // 获取展开项和选中项 defaultExpanded.value = temp.expandList defaultChecked.value = temp.openedList tree.value.setCheckedKeys(temp.openedList) loading.value = false } }) } interface treeItem { expanded: boolean childNodes?: treeItem[] } /** * 改变树节点展开状态,递归 * @param node 改变的节点 * @param value 展开/折叠 */ function changeTreeNodeStatus(node: treeItem, value: boolean) { node.expanded = value // 给当前节点赋值 if (node.childNodes) { for (let i = 0; i < node.childNodes.length; i++) { // 给子节点赋值 node.childNodes[i].expanded = value if (node.childNodes[i].childNodes && node.childNodes[i].childNodes!.length > 0) { // 如果子节点还有子节点,递归 changeTreeNodeStatus(node.childNodes[i], value) } } } } // 点击展开或折叠按钮 function expandOrCollapse() { treeExpand.value = !treeExpand.value changeTreeNodeStatus(tree.value.store.root, treeExpand.value) } // 全选或全不选 function handleCheckedTreeNodeAll(value: boolean) { tree.value.setCheckedKeys(value ? resourceIds.value : []) } const filterNode = (value: string, data: { name: string }) => data.name?.includes(value) // 监控查询框 watch(filterText, (val) => { tree.value!.filter(val) }) // ----------初始化、关闭对话框相关----------------- function initDialog(row: RoleInfo) { roleName.value = row.name roleId.value = row.id dialogVisible.value = true btnLoading.value = false fetchResourceTree(row.id) } // 关闭弹窗 function dialogClose() { dialogVisible.value = false } // ----------------------- 以下是暴露的方法内容 ---------------------------- defineExpose({ initDialog }) </script> <template> <ElDialog v-model="dialogVisible" :title="roleName" width="400" :before-close="dialogClose" append-to-body :open-delay="0" :close-on-click-modal="false" > <div class="tool-line"> <ElButton :icon="Switch" style="margin-bottom: 10px;" @click="expandOrCollapse"> 展开/折叠 </ElButton> <el-checkbox v-model="nodeCheckedAll" style="margin-left: 16px;" @change="handleCheckedTreeNodeAll($event)"> 全选 </el-checkbox> <el-checkbox v-model="treeCheckStrictly"> 父子联动 </el-checkbox> </div> <el-input v-model="filterText" placeholder="关键词过滤" style="margin-bottom: 15px;" /> <el-scrollbar height="400px"> <el-tree ref="tree" v-loading="loading" :props="defaultProps" :data="treeList" :default-expanded-keys="defaultExpanded" :default-checked-keys="defaultChecked" :check-strictly="!treeCheckStrictly" :filter-node-method="filterNode" show-checkbox node-key="id" /> </el-scrollbar> <template #footer> <div class="dialog-footer"> <ElButton :loading="btnLoading" type="primary" @click="submitForm"> 保存 </ElButton> <ElButton @click="dialogClose"> 取消 </ElButton> </div> </template> </ElDialog> </template> <style lang="scss" scoped> .tool-line { margin-bottom: 5px; margin-top: -15px; } </style>