feat:角色 role 的数据权限 80%

pull/62/head
YunaiV 2025-03-31 16:53:51 +08:00
parent 108d13b896
commit 36838c910b
5 changed files with 105 additions and 76 deletions

View File

@ -0,0 +1,57 @@
import { requestClient } from '#/api/request';
export namespace SystemPermissionApi {
/** 分配用户角色请求 */
export interface AssignUserRoleReqVO {
userId: number;
roleIds: number[];
}
/** 分配角色菜单请求 */
export interface AssignRoleMenuReqVO {
roleId: number;
menuIds: number[];
}
/** 分配角色数据权限请求 */
export interface AssignRoleDataScopeReqVO {
roleId: number;
dataScope: number;
dataScopeDeptIds: number[];
}
}
/** 查询角色拥有的菜单权限 */
export async function getRoleMenuList(roleId: number) {
return requestClient.get(
`/system/permission/list-role-menus?roleId=${roleId}`,
);
}
/** 赋予角色菜单权限 */
export async function assignRoleMenu(
data: SystemPermissionApi.AssignRoleMenuReqVO,
) {
return requestClient.post('/system/permission/assign-role-menu', data);
}
/** 赋予角色数据权限 */
export async function assignRoleDataScope(
data: SystemPermissionApi.AssignRoleDataScopeReqVO,
) {
return requestClient.post('/system/permission/assign-role-data-scope', data);
}
/** 查询用户拥有的角色数组 */
export async function getUserRoleList(userId: number) {
return requestClient.get(
`/system/permission/list-user-roles?userId=${userId}`,
);
}
/** 赋予用户角色 */
export async function assignUserRole(
data: SystemPermissionApi.AssignUserRoleReqVO,
) {
return requestClient.post('/system/permission/assign-user-role', data);
}

View File

@ -11,7 +11,7 @@ import { DICT_TYPE, getDictOptions } from '#/utils/dict';
import { CommonStatusEnum } from '#/utils/constants';
import { handleTree } from '#/utils/tree';
/** 获取编辑表单的字段配置 */
/** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] {
return [
{
@ -123,7 +123,7 @@ export function useFormSchema(): VbenFormSchema[] {
];
}
/** 获取表格列配置 */
/** 列表的字段 */
const userList = await getSimpleUserList();
export function useGridColumns(
onActionClick?: OnActionClickFn<SystemDeptApi.SystemDept>,

View File

@ -5,6 +5,7 @@ import type { SystemPostApi } from '#/api/system/post';
import { DICT_TYPE, getDictOptions } from '#/utils/dict';
import { CommonStatusEnum } from '#/utils/constants';
/** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] {
return [
{
@ -59,6 +60,7 @@ export function useFormSchema(): VbenFormSchema[] {
];
}
/** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] {
return [
{
@ -83,6 +85,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
];
}
/** 列表的字段 */
export function useGridColumns<T = SystemPostApi.SystemPost>(
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {

View File

@ -1,7 +1,8 @@
import {type VbenFormSchema, z} from '#/adapter/form';
import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemRoleApi } from '#/api/system/role';
import { z } from '#/adapter/form';
import { DICT_TYPE, getDictOptions } from '#/utils/dict';
import { CommonStatusEnum, SystemDataScopeEnum } from '#/utils/constants';
@ -56,7 +57,7 @@ export function useFormSchema(): VbenFormSchema[] {
component: 'Textarea',
fieldName: 'remark',
label: '角色备注',
}
},
];
}
@ -78,7 +79,7 @@ export function useAssignDataPermissionFormSchema(): VbenFormSchema[] {
label: '角色名称',
componentProps: {
disabled: true,
}
},
},
{
component: 'Input',
@ -86,7 +87,7 @@ export function useAssignDataPermissionFormSchema(): VbenFormSchema[] {
label: '角色标识',
componentProps: {
disabled: true,
}
},
},
{
component: 'Select',
@ -95,22 +96,22 @@ export function useAssignDataPermissionFormSchema(): VbenFormSchema[] {
componentProps: {
class: 'w-full',
options: getDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE, 'number'),
}
},
},
{
component: 'Input',
fieldName: 'dataScopeDeptIds',
label: '部门范围',
// dependencies: {
// triggerFields: ['dataScope'],
// show: (values) => {
// return values.dataScope === SystemDataScopeEnum.DEPT_CUSTOM;
// }
// },
formItemClass: 'items-start', // TODO @芋艿:
modelPropName: 'modelValue', // TODO @芋艿:
}
]
dependencies: {
triggerFields: ['dataScope'],
show: (values) => {
return values.dataScope === SystemDataScopeEnum.DEPT_CUSTOM;
},
},
formItemClass: 'items-start',
modelPropName: 'modelValue', // TODO @芋艿:这个是不是可以去掉哈
},
];
}
/** 列表的搜索表单 */
@ -224,4 +225,3 @@ export function useGridColumns<T = SystemRoleApi.SystemRole>(
}
// TODO @芋艿:角色分配
// TODO @芋艿:数据权限

View File

@ -1,24 +1,27 @@
<script lang="ts" setup>
import type { SystemRoleApi } from '#/api/system/role';
import type { SystemDeptApi } from '#/api/system/dept';
import { ref } from 'vue';
import { VbenTree } from '@vben/common-ui';
import { useVbenModal } from '@vben/common-ui';
import { Button, message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { createRole, updateRole, getRole } from '#/api/system/role';
import { ref } from 'vue';
import { $t } from '#/locales';
import { useVbenForm } from '#/adapter/form';
import { getRole } from '#/api/system/role';
import { assignRoleDataScope} from '#/api/system/permission';
import { getDeptList } from '#/api/system/dept';
import { handleTree } from '#/utils/tree';
import { useAssignDataPermissionFormSchema } from '../data';
import { SystemDataScopeEnum } from '#/utils/constants';
const emit = defineEmits(['success']);
const formData = ref<SystemRoleApi.SystemRole>();
// TODO @
import { getDeptList, type SystemDeptApi } from '#/api/system/dept';
import { handleTree } from '#/utils/tree';
import type { Recordable } from '@vben-core/typings';
const deptTree = ref<SystemDeptApi.SystemDept[]>([]); //
const deptLoading = ref(false); //
const [Form, formApi] = useVbenForm({
layout: 'horizontal',
@ -38,11 +41,13 @@ const [Modal, modalApi] = useVbenModal({
return;
}
modalApi.lock();
const data = (await formApi.getValues()) as SystemRoleApi.SystemRole;
const data = await formApi.getValues();
try {
await (formData.value?.id
? updateRole(data)
: createRole(data));
await assignRoleDataScope({
roleId: data.id,
dataScope: data.dataScope,
dataScopeDeptIds: data.dataScope === SystemDataScopeEnum.DEPT_CUSTOM ? data.dataScopeDeptIds : undefined,
});
await modalApi.close();
emit('success');
message.success({
@ -65,54 +70,36 @@ const [Modal, modalApi] = useVbenModal({
try {
formData.value = await getRole(data.id as number);
await formApi.setValues(formData.value);
await loadPermissions();
//
await loadDeptTree();
} finally {
modalApi.lock(false);
}
},
});
// TODO
const permissions = ref<SystemDeptApi.SystemDept[]>([]);
const loadingPermissions = ref(false);
// TODO
async function loadPermissions() {
loadingPermissions.value = true;
/** 加载部门树 */
async function loadDeptTree() {
deptLoading.value = true;
try {
debugger
const res = await getDeptList();
permissions.value = handleTree(res);
deptTree.value = handleTree(res);
} finally {
loadingPermissions.value = false;
deptLoading.value = false;
}
}
// TODO
function getNodeClass(node: Recordable<any>) {
const classes: string[] = [];
if (node.value?.type === 'button') {
classes.push('inline-flex');
if (node.index % 3 >= 1) {
classes.push('!pl-0');
}
}
return classes.join(' ');
}
</script>
<template>
<Modal title="数据权限">
<Form class="mx-4">
<template #dataScopeDeptIds="slotProps">
<Spin :spinning="loadingPermissions" wrapper-class-name="w-full">
<Spin :spinning="deptLoading" class="w-full">
<VbenTree
:tree-data="permissions"
:tree-data="deptTree"
multiple
bordered
:default-expanded-level="2"
:get-node-class="getNodeClass"
v-bind="slotProps"
value-field="id"
label-field="name"
@ -129,21 +116,3 @@ function getNodeClass(node: Recordable<any>) {
</template>
</Modal>
</template>
<!-- TODO @芋艿测试 -->
<style lang="css" scoped>
:deep(.ant-tree-title) {
.tree-actions {
display: none;
margin-left: 20px;
}
}
:deep(.ant-tree-title:hover) {
.tree-actions {
display: flex;
flex: auto;
justify-content: flex-end;
margin-left: 20px;
}
}
</style>