|
@@ -4,10 +4,11 @@
|
|
|
<div class="flex items-center">
|
|
|
<span class="m-r-base">角色</span>
|
|
|
<base-select v-model="role" :options="ROLE_OPTION"></base-select>
|
|
|
- <el-button class="m-l-base" type="primary">保存</el-button>
|
|
|
+ <el-button class="m-l-base" type="primary" :loading="loading" @click="onSubmit">保存</el-button>
|
|
|
</div>
|
|
|
<div class="flex-1 p-base m-t-large fill-lighter full-scroll-y-auto privilege-tree">
|
|
|
- <el-tree show-checkbox :data="[result]"> </el-tree>
|
|
|
+ <el-tree ref="treeRef" show-checkbox node-key="index" :data="menuTree || []" @check-change="onCheckChange">
|
|
|
+ </el-tree>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -15,22 +16,78 @@
|
|
|
|
|
|
<script setup lang="ts" name="RoleSetting">
|
|
|
/** 角色权限管理 */
|
|
|
-import { reactive, ref, watch } from 'vue'
|
|
|
+import { computed, nextTick, ref, watch } from 'vue'
|
|
|
import { ElButton, ElTree } from 'element-plus'
|
|
|
-import BaseSelect from '@/components/element/BaseSelect.vue'
|
|
|
import { ROLE_OPTION } from '@/constants/dicts'
|
|
|
import useFetch from '@/hooks/useFetch'
|
|
|
+import useMainLayoutStore from '@/store/layout'
|
|
|
+import BaseSelect from '@/components/element/BaseSelect.vue'
|
|
|
+
|
|
|
+import type { ExtractApiResponse } from 'api-type'
|
|
|
+
|
|
|
+type MenuItem = MainLayoutStore.MenuItem
|
|
|
+
|
|
|
+type MenuItemWithId = MenuItem & { id: number }
|
|
|
|
|
|
const props = defineProps<{ role: ROLE }>()
|
|
|
|
|
|
+const mainLayoutStore = useMainLayoutStore()
|
|
|
+
|
|
|
const role = ref<ROLE>(props.role)
|
|
|
|
|
|
-const { fetch: getPrivilege, result } = useFetch('getRolePrivilege')
|
|
|
-const { fetch: setPrivilege } = useFetch('setRolePrivilege')
|
|
|
+const treeRef = ref<InstanceType<typeof ElTree>>()
|
|
|
+
|
|
|
+const checkedMenus = ref<MenuItemWithId[]>([])
|
|
|
+
|
|
|
+const { fetch: getPrivilege, result: privilege } = useFetch('getRolePrivilege')
|
|
|
+
|
|
|
+const { fetch: setPrivilege, loading } = useFetch('setRolePrivilege')
|
|
|
|
|
|
-watch(role, () => {
|
|
|
- getPrivilege({ role: role.value })
|
|
|
+watch(
|
|
|
+ role,
|
|
|
+ () => {
|
|
|
+ role.value && getPrivilege({ role: role.value })
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+)
|
|
|
+
|
|
|
+watch(privilege, () => {
|
|
|
+ nextTick(() => {
|
|
|
+ treeRef?.value?.setCheckedKeys(privilege?.value?.filter((d) => d.hasPrivilege)?.map((d) => d.code))
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+function filterPrivilege(
|
|
|
+ item: MenuItem,
|
|
|
+ privilege: ExtractApiResponse<'getRolePrivilege'>
|
|
|
+): MenuItemWithId | undefined {
|
|
|
+ const privilegeItem = privilege.find((d) => item.index === d.code)
|
|
|
+ if (privilegeItem) {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ id: privilegeItem.id,
|
|
|
+ children: item.children?.map((child) => filterPrivilege(child, privilege)).filter((d) => !!d) as MenuItemWithId[],
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const menuTree = computed(() => {
|
|
|
+ return mainLayoutStore.menuList?.reduce((menus, menu) => {
|
|
|
+ return menus.concat(filterPrivilege(menu, privilege.value || []) || [])
|
|
|
+ }, [] as MenuItem[])
|
|
|
})
|
|
|
+
|
|
|
+const onCheckChange = () => {
|
|
|
+ checkedMenus.value = (treeRef?.value?.getCheckedNodes() as MenuItemWithId[]) || []
|
|
|
+}
|
|
|
+
|
|
|
+/** 保存 */
|
|
|
+const onSubmit = () => {
|
|
|
+ const checkedNodes = treeRef?.value?.getCheckedNodes() || []
|
|
|
+ const checkedHalfNodes = treeRef?.value?.getHalfCheckedNodes() || []
|
|
|
+ const privilegeIds = checkedNodes.concat(checkedHalfNodes).map((d) => d.id)
|
|
|
+ setPrivilege({ role: role.value, privilegeIds })
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|