feat:角色添加权限
This commit is contained in:
@@ -110,10 +110,11 @@ export function updateRoleMenu(roleId: number, menuIds: Array<Number>) {
|
|||||||
*
|
*
|
||||||
* @param roleId
|
* @param roleId
|
||||||
*/
|
*/
|
||||||
export function listRolePerms(roleId: number) {
|
export function listRolePerms(roleId: number, menuId: number) {
|
||||||
return request({
|
return request({
|
||||||
url: '/youlai-admin/api/v1/roles/' + roleId + '/permissions',
|
url: '/youlai-admin/api/v1/roles/' + roleId + '/permissions',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
data: {menuId: menuId}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +125,7 @@ export function listRolePerms(roleId: number) {
|
|||||||
* @param roleId
|
* @param roleId
|
||||||
* @param permIds
|
* @param permIds
|
||||||
*/
|
*/
|
||||||
export function saveRolePerms(menuId: number, roleId: number, permIds: Array<number>) {
|
export function saveRolePerms(roleId: number, menuId: number, permIds: Array<number>) {
|
||||||
return request({
|
return request({
|
||||||
url: '/youlai-admin/api/v1/roles/' + roleId + '/permissions',
|
url: '/youlai-admin/api/v1/roles/' + roleId + '/permissions',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="width: 100%;">
|
<div class="menu-container">
|
||||||
<el-form size="mini">
|
<el-form size="mini">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-row>
|
<el-row>
|
||||||
@@ -13,17 +13,16 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
|
|
||||||
<el-tree
|
<el-tree
|
||||||
ref="menuRef"
|
ref="menuRef"
|
||||||
v-if="state.refreshTree"
|
v-if="refreshTree"
|
||||||
:default-expanded-keys="state.expandedKeys"
|
:default-expanded-keys="expandedKeys"
|
||||||
:default-expand-all="state.isExpandAll"
|
:default-expand-all="isExpandAll"
|
||||||
:data="state.menuOptions"
|
:data="menuOptions"
|
||||||
show-checkbox
|
show-checkbox
|
||||||
node-key="id"
|
node-key="id"
|
||||||
empty-text="加载菜单中..."
|
empty-text="加载菜单中..."
|
||||||
:check-strictly="state.checkStrictly"
|
:check-strictly="checkStrictly"
|
||||||
highlight-current
|
highlight-current
|
||||||
@node-click="handleNodeClick"
|
@node-click="handleNodeClick"
|
||||||
/>
|
/>
|
||||||
@@ -33,9 +32,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {listTreeSelectMenus} from "@/api/system/menu";
|
import {listTreeSelectMenus} from "@/api/system/menu";
|
||||||
import {listRoleMenuIds, updateRoleMenu} from "@/api/system/role"
|
import {listRoleMenuIds, updateRoleMenu} from "@/api/system/role"
|
||||||
import {defineEmits, defineProps, nextTick, onMounted, reactive, ref, watch} from "vue"
|
import {defineEmits, defineProps, nextTick, onMounted, reactive, ref, toRefs, watch} from "vue"
|
||||||
import {ElTree, ElMessage, ElMessageBox} from "element-plus"
|
import {ElTree, ElMessage, ElMessageBox} from "element-plus"
|
||||||
|
|
||||||
import {Switch, Check} from '@element-plus/icons'
|
import {Switch, Check} from '@element-plus/icons'
|
||||||
|
|
||||||
const emit = defineEmits(['menuClick'])
|
const emit = defineEmits(['menuClick'])
|
||||||
@@ -68,6 +66,8 @@ const state = reactive({
|
|||||||
refreshTree: true
|
refreshTree: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const {expandedKeys, menuOptions, checkStrictly, isExpandAll, refreshTree} = toRefs(state)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载菜单树
|
* 加载菜单树
|
||||||
*/
|
*/
|
||||||
@@ -109,5 +109,7 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.menu-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,39 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="perm-container">
|
<div class="perm-container">
|
||||||
<el-card class="box-card" shadow="always">
|
<el-form size="mini">
|
||||||
<div class="clearfix" slot="header">
|
<el-form-item>
|
||||||
<b>
|
<el-row>
|
||||||
<svg-icon icon-class="menu"/>
|
<el-col :span="12">
|
||||||
{{ menu && menu.label ? "【" + menu.label + "】" : "" }}权限分配
|
<el-button type="success" plain :icon="Switch" @click="toggleExpandAll">展开/折叠</el-button>
|
||||||
</b>
|
|
||||||
</div>
|
|
||||||
<el-row style="margin-bottom: 10px">
|
|
||||||
<el-col :span="18">
|
|
||||||
<el-tag v-if="role" type="primary">{{ role.name }}</el-tag>
|
|
||||||
<el-tag v-if="menu" type="success" style="margin-left: 5px">{{
|
|
||||||
menu.label
|
|
||||||
}}
|
|
||||||
</el-tag>
|
|
||||||
<el-tag v-if="!role" type="info" style="margin-left: 5px"
|
|
||||||
><i class="el-icon-info"> </i> 请选择角色
|
|
||||||
</el-tag>
|
|
||||||
<el-tag v-if="!menu" type="info" style="margin-left: 5px"
|
|
||||||
><i class="el-icon-info"> </i> 请选择菜单
|
|
||||||
</el-tag>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6" style="text-align: right">
|
<el-col :span="12" style="text-align: right">
|
||||||
<el-button
|
<el-button type="primary" :icon="Check" @click="handleSubmit">提交</el-button>
|
||||||
type="primary"
|
|
||||||
:disabled="isRoot"
|
|
||||||
icon="el-icon-check"
|
|
||||||
size="mini"
|
|
||||||
@click="handleSubmit"
|
|
||||||
>提交
|
|
||||||
</el-button>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
<div v-if="permissionList.length > 0">
|
|
||||||
|
<div v-if="permissionOptions.length > 0">
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
:indeterminate="isIndeterminate"
|
:indeterminate="isIndeterminate"
|
||||||
v-model="checkAll"
|
v-model="checkAll"
|
||||||
@@ -44,15 +25,15 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col
|
<el-col
|
||||||
:span="8"
|
:span="8"
|
||||||
v-for="permission in permissionList"
|
v-for="item in permissionOptions"
|
||||||
style="margin-top: 20px"
|
style="margin-top: 20px"
|
||||||
>
|
>
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
border
|
border
|
||||||
v-model="permission.checked"
|
v-model="item.checked"
|
||||||
:label="permission.id"
|
:label="item.id"
|
||||||
:key="permission.id"
|
:key="item.id"
|
||||||
@change="handleCheckChange"
|
@change="handleCheckedPermChange"
|
||||||
size="mini"
|
size="mini"
|
||||||
>
|
>
|
||||||
{{ permission.name }}
|
{{ permission.name }}
|
||||||
@@ -63,125 +44,111 @@
|
|||||||
<div style="text-align: center" v-else>
|
<div style="text-align: center" v-else>
|
||||||
<el-empty :description=" !role? '请选择角色': !menu? '请选择菜单': '暂无数据,您可在【菜单管理】配置权限数据'"></el-empty>
|
<el-empty :description=" !role? '请选择角色': !menu? '请选择菜单': '暂无数据,您可在【菜单管理】配置权限数据'"></el-empty>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import {getPermissionList} from "@/api/system/permission";
|
import {listPerms} from "@/api/system/perm";
|
||||||
import {listRolePermission, updateRolePermission} from "@/api/system/role";
|
import { listRolePerms, saveRolePerms} from "@/api/system/role";
|
||||||
|
import {defineProps, onMounted, reactive, toRefs, watch} from "vue";
|
||||||
|
import {ElMessage} from "element-plus";
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "Permission",
|
const props = defineProps({
|
||||||
props: ["type"],
|
role: {
|
||||||
data() {
|
type: Object,
|
||||||
return {
|
default: {}
|
||||||
|
},
|
||||||
|
menu: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => props.role.id as any, (newVal, oldVal) => {
|
||||||
|
const roleId = props.role.id
|
||||||
|
if (roleId) {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => props.menu.id as any, (newVal, oldVal) => {
|
||||||
|
const menuId = props.menu.id
|
||||||
|
if (menuId) {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
loading: false,
|
loading: false,
|
||||||
ids: [],
|
permissionOptions: [] as Array<any>,
|
||||||
initialCheckedPermissionIds: [],
|
|
||||||
menu: undefined,
|
|
||||||
role: undefined,
|
|
||||||
isIndeterminate: true,
|
isIndeterminate: true,
|
||||||
checkAll: false,
|
checkAll: false,
|
||||||
permissionList: [],
|
checkedPerms: []
|
||||||
isRoot: false,
|
})
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleQuery() {
|
|
||||||
this.loading = true;
|
|
||||||
const menuId = this.menu.value;
|
|
||||||
getPermissionList({
|
|
||||||
menuId: menuId
|
|
||||||
}).then((response) => {
|
|
||||||
const {data} = response;
|
|
||||||
if (this.role.code == this.ROOT_ROLE_CODE) {
|
|
||||||
// 如果是超级管理员默认勾选全部且不可编辑
|
|
||||||
this.isRoot = true
|
|
||||||
this.checkAll = true
|
|
||||||
this.isIndeterminate = false
|
|
||||||
data.map((item) => this.$set(item, "checked", true))
|
|
||||||
this.permissionList = data
|
|
||||||
this.loading = false
|
|
||||||
} else {
|
|
||||||
this.isRoot = false;
|
|
||||||
listRolePermission(this.role.id, {menuId: menuId}).then((res) => {
|
|
||||||
this.initialCheckedPermissionIds = res.data;
|
|
||||||
let checkAll = true
|
|
||||||
data.map((item) => {
|
|
||||||
if (this.initialCheckedPermissionIds.includes(item.id)) {
|
|
||||||
item.checked = true;
|
|
||||||
} else {
|
|
||||||
checkAll = false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.checkAll = checkAll
|
|
||||||
if (checkAll) {
|
|
||||||
this.isIndeterminate = false
|
|
||||||
}
|
|
||||||
this.permissionList = data;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
menuClick(menu, role) {
|
|
||||||
this.role = role;
|
|
||||||
this.menu = menu;
|
|
||||||
|
|
||||||
if (role && menu) {
|
const {permissionOptions, isIndeterminate, checkAll, checkedPerms} = toRefs(state)
|
||||||
this.handleQuery();
|
|
||||||
} else {
|
function handleCheckAllChange(checked: Boolean) {
|
||||||
this.permissionList = [];
|
state.isIndeterminate = false;
|
||||||
this.initialCheckedPermissionIds = [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleSubmit: function () {
|
|
||||||
const checkedPermissionIds = this.permissionList
|
|
||||||
.filter((item) => item.checked)
|
|
||||||
.map((item) => item.id);
|
|
||||||
// 判断选中权限是否变动
|
|
||||||
if (
|
|
||||||
this.initialCheckedPermissionIds.length ==
|
|
||||||
checkedPermissionIds.length &&
|
|
||||||
this.initialCheckedPermissionIds.sort().every(function (v, i) {
|
|
||||||
return v == checkedPermissionIds[i];
|
|
||||||
})
|
|
||||||
) {
|
|
||||||
this.$message.warning("数据未变动");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateRolePermission(
|
|
||||||
this.menu.value,
|
|
||||||
this.role.id,
|
|
||||||
checkedPermissionIds
|
|
||||||
).then((response) => {
|
|
||||||
this.$message.success("提交成功");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleCheckAllChange(checked) {
|
|
||||||
if (checked) {
|
if (checked) {
|
||||||
this.permissionList.map((item) => (item.checked = true));
|
state.permissionOptions.map((item) => (item.checked = true));
|
||||||
} else {
|
} else {
|
||||||
// 全不选
|
// 全不选
|
||||||
this.permissionList.map((item) => (item.checked = false));
|
state.permissionOptions.map((item) => (item.checked = false));
|
||||||
}
|
}
|
||||||
this.isIndeterminate = false;
|
}
|
||||||
},
|
|
||||||
handleCheckChange(item, val) {
|
function handleCheckedPermChange(value: any) {
|
||||||
const checkedCount = this.permissionList.filter(
|
const checkedCount = value.length;
|
||||||
(item) => item.checked
|
state.checkAll = checkedCount === state.permissionOptions.length;
|
||||||
).length;
|
state.isIndeterminate = checkedCount > 0 && checkedCount < state.permissionOptions.length;
|
||||||
this.checkAll = checkedCount === this.permissionList.length;
|
}
|
||||||
this.isIndeterminate =
|
|
||||||
checkedCount > 0 && checkedCount < this.permissionList.length;
|
function loadData() {
|
||||||
},
|
if(! props.menu.id){
|
||||||
},
|
return false
|
||||||
};
|
}
|
||||||
|
|
||||||
|
state.loading = true;
|
||||||
|
listPerms({menuId: props.menu.id}).then(response => {
|
||||||
|
state.permissionOptions = response.data
|
||||||
|
listRolePerms(props.role.id, props.menu.id).then(res => {
|
||||||
|
const checkedPermIds = res.data
|
||||||
|
state.permissionOptions.map((item:any)=> {
|
||||||
|
if (checkedPermIds.includes(item.id)) {
|
||||||
|
item.checked = true;
|
||||||
|
} else {
|
||||||
|
state.checkAll = false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
state.loading=false
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSubmit(){
|
||||||
|
const checkedPermIds = state.permissionOptions
|
||||||
|
.filter((item) => item.checked)
|
||||||
|
.map((item) => item.id);
|
||||||
|
|
||||||
|
|
||||||
|
saveRolePerms( props.menu.id,
|
||||||
|
props.role.id,
|
||||||
|
checkedPermIds
|
||||||
|
).then(() => {
|
||||||
|
ElMessage.success("提交成功");
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadData()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.perm-container {
|
.perm-container {
|
||||||
margin-bottom: 20px;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -17,7 +17,10 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<svg-icon color="#333" icon-class="menu"/>
|
<svg-icon color="#333" icon-class="menu"/>
|
||||||
<span style="margin:0 5px;">菜单分配</span>
|
<span style="margin:0 5px;">菜单分配</span>
|
||||||
<el-tag type="success" v-if="state.role.id" size="small"> <svg-icon color="green " icon-class="role"/> {{ state.role.name }}</el-tag>
|
<el-tag type="success" v-if="state.role.id" size="small">
|
||||||
|
<svg-icon color="green " icon-class="role"/>
|
||||||
|
{{ state.role.name }}
|
||||||
|
</el-tag>
|
||||||
<el-tag type="warning" v-else size="small">请选择角色</el-tag>
|
<el-tag type="warning" v-else size="small">请选择角色</el-tag>
|
||||||
</template>
|
</template>
|
||||||
<menus ref="menu" @menuClick="handleMenuClick" :role="state.role"/>
|
<menus ref="menu" @menuClick="handleMenuClick" :role="state.role"/>
|
||||||
@@ -30,13 +33,19 @@
|
|||||||
<svg-icon color="#333" icon-class="perm"/>
|
<svg-icon color="#333" icon-class="perm"/>
|
||||||
<span style="margin:0 5px;">权限分配</span>
|
<span style="margin:0 5px;">权限分配</span>
|
||||||
|
|
||||||
<el-tag type="success" style="margin:0 5px 0 0;" v-if="state.role.id" size="small"> <svg-icon color="green" icon-class="role"/> {{ state.role.name }}</el-tag>
|
<el-tag type="success" style="margin:0 5px 0 0;" v-if="state.role.id" size="small">
|
||||||
|
<svg-icon color="green" icon-class="role"/>
|
||||||
|
{{ state.role.name }}
|
||||||
|
</el-tag>
|
||||||
<el-tag type="warning" style="margin:0 5px 0 0;" v-else size="small"> 请选择角色</el-tag>
|
<el-tag type="warning" style="margin:0 5px 0 0;" v-else size="small"> 请选择角色</el-tag>
|
||||||
|
|
||||||
<el-tag type="primary" v-if="state.role.id" size="small"><svg-icon color="red" icon-class="menu"/> {{ state.role.name }}</el-tag>
|
<el-tag type="primary" v-if="state.role.id" size="small">
|
||||||
|
<svg-icon color="red" icon-class="menu"/>
|
||||||
|
{{ state.role.name }}
|
||||||
|
</el-tag>
|
||||||
<el-tag type="warning" v-else size="small"> 请选择菜单</el-tag>
|
<el-tag type="warning" v-else size="small"> 请选择菜单</el-tag>
|
||||||
</template>
|
</template>
|
||||||
<!--<perm ref="perm" :menu="state.menu" :role="state.role"/>-->
|
<perm ref="perm" :menu="state.menu" :role="state.role"/>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
@@ -47,6 +56,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Role from './components/Role.vue'
|
import Role from './components/Role.vue'
|
||||||
import Menus from './components/Menu.vue'
|
import Menus from './components/Menu.vue'
|
||||||
|
import Perm from './components/Perm.vue'
|
||||||
import {reactive} from "vue";
|
import {reactive} from "vue";
|
||||||
import {ElMessage} from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
import SvgIcon from '@/components/SvgIcon/index.vue';
|
import SvgIcon from '@/components/SvgIcon/index.vue';
|
||||||
|
|||||||
Reference in New Issue
Block a user