增加角色批量授权用户
(cherry picked commit from <gitee.com//lxy0722/django-vue3-admin/commit/702eb7d7aeb2a9c30416a8ebb503a4b8e3367492>
This commit is contained in:
@@ -10,16 +10,17 @@ from rest_framework import serializers
|
|||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
|
||||||
from dvadmin.system.models import Role, Menu, MenuButton, Dept
|
from dvadmin.system.models import Role, Menu, MenuButton, Dept, Users
|
||||||
from dvadmin.system.views.dept import DeptSerializer
|
from dvadmin.system.views.dept import DeptSerializer
|
||||||
from dvadmin.system.views.menu import MenuSerializer
|
from dvadmin.system.views.menu import MenuSerializer
|
||||||
from dvadmin.system.views.menu_button import MenuButtonSerializer
|
from dvadmin.system.views.menu_button import MenuButtonSerializer
|
||||||
from dvadmin.utils.crud_mixin import FastCrudMixin
|
from dvadmin.utils.crud_mixin import FastCrudMixin
|
||||||
from dvadmin.utils.field_permission import FieldPermissionMixin
|
from dvadmin.utils.field_permission import FieldPermissionMixin
|
||||||
from dvadmin.utils.json_response import SuccessResponse, DetailResponse
|
from dvadmin.utils.json_response import SuccessResponse, DetailResponse, ErrorResponse
|
||||||
from dvadmin.utils.serializers import CustomModelSerializer
|
from dvadmin.utils.serializers import CustomModelSerializer
|
||||||
from dvadmin.utils.validator import CustomUniqueValidator
|
from dvadmin.utils.validator import CustomUniqueValidator
|
||||||
from dvadmin.utils.viewset import CustomModelViewSet
|
from dvadmin.utils.viewset import CustomModelViewSet
|
||||||
|
from dvadmin.utils.permission import CustomPermission
|
||||||
|
|
||||||
|
|
||||||
class RoleSerializer(CustomModelSerializer):
|
class RoleSerializer(CustomModelSerializer):
|
||||||
@@ -107,7 +108,6 @@ class MenuButtonPermissionSerializer(CustomModelSerializer):
|
|||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RoleViewSet(CustomModelViewSet, FastCrudMixin,FieldPermissionMixin):
|
class RoleViewSet(CustomModelViewSet, FastCrudMixin,FieldPermissionMixin):
|
||||||
"""
|
"""
|
||||||
角色管理接口
|
角色管理接口
|
||||||
@@ -142,3 +142,62 @@ class RoleViewSet(CustomModelViewSet, FastCrudMixin,FieldPermissionMixin):
|
|||||||
role.users_set.add(*movedKeys)
|
role.users_set.add(*movedKeys)
|
||||||
serializer = RoleSerializer(role)
|
serializer = RoleSerializer(role)
|
||||||
return DetailResponse(data=serializer.data, msg="更新成功")
|
return DetailResponse(data=serializer.data, msg="更新成功")
|
||||||
|
|
||||||
|
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated, CustomPermission])
|
||||||
|
def get_role_users(self, request):
|
||||||
|
"""
|
||||||
|
获取角色已授权、未授权的用户
|
||||||
|
已授权的用户:1
|
||||||
|
未授权的用户:0
|
||||||
|
"""
|
||||||
|
role_id = request.query_params.get('role_id', None)
|
||||||
|
|
||||||
|
if not role_id:
|
||||||
|
return ErrorResponse(msg="请选择角色")
|
||||||
|
|
||||||
|
if request.query_params.get('authorized', 0) == "1":
|
||||||
|
queryset = Users.objects.filter(role__id=role_id).exclude(is_superuser=True)
|
||||||
|
else:
|
||||||
|
queryset = Users.objects.exclude(role__id=role_id).exclude(is_superuser=True)
|
||||||
|
|
||||||
|
if name := request.query_params.get('name', None):
|
||||||
|
queryset = queryset.filter(name__icontains=name)
|
||||||
|
|
||||||
|
if dept := request.query_params.get('dept', None):
|
||||||
|
queryset = queryset.filter(dept=dept)
|
||||||
|
|
||||||
|
page = self.paginate_queryset(queryset.values('id', 'name', 'dept__name'))
|
||||||
|
if page is not None:
|
||||||
|
return self.get_paginated_response(page)
|
||||||
|
|
||||||
|
return SuccessResponse(data=page)
|
||||||
|
|
||||||
|
@action(methods=['DELETE'], detail=True, permission_classes=[IsAuthenticated, CustomPermission])
|
||||||
|
def remove_role_user(self, request, pk):
|
||||||
|
"""
|
||||||
|
角色-删除用户
|
||||||
|
"""
|
||||||
|
user_id = request.data.get('user_id', None)
|
||||||
|
|
||||||
|
if not user_id:
|
||||||
|
return ErrorResponse(msg="请选择用户")
|
||||||
|
|
||||||
|
role = self.get_object()
|
||||||
|
role.users_set.remove(*user_id)
|
||||||
|
|
||||||
|
return SuccessResponse(msg="删除成功")
|
||||||
|
|
||||||
|
@action(methods=['POST'], detail=True, permission_classes=[IsAuthenticated, CustomPermission])
|
||||||
|
def add_role_users(self, request, pk):
|
||||||
|
"""
|
||||||
|
角色-添加用户
|
||||||
|
"""
|
||||||
|
users_id = request.data.get('users_id', None)
|
||||||
|
|
||||||
|
if not users_id:
|
||||||
|
return ErrorResponse(msg="请选择用户")
|
||||||
|
|
||||||
|
role = self.get_object()
|
||||||
|
role.users_set.add(*users_id)
|
||||||
|
|
||||||
|
return DetailResponse(msg="添加成功")
|
||||||
|
|||||||
30
web/src/views/system/role/components/addUsers/api.ts
Normal file
30
web/src/views/system/role/components/addUsers/api.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { request } from '/@/utils/service';
|
||||||
|
import { UserPageQuery} from '@fast-crud/fast-crud';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前角色查询未授权的用户
|
||||||
|
* @param role_id 角色id
|
||||||
|
* @param query 查询条件 需要有角色id
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getRoleUsersUnauthorized(query: UserPageQuery) {
|
||||||
|
query["authorized"] = 0; // 未授权的用户
|
||||||
|
return request({
|
||||||
|
url: '/api/system/role/get_role_users/',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 当前用户角色添加用户
|
||||||
|
* @param role_id 角色id
|
||||||
|
* @param users_id 用户id数组
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function addRoleUsers(role_id: number, users_id: Array<Number>) {
|
||||||
|
return request({
|
||||||
|
url: `/api/system/role/${role_id}/add_role_users/`,
|
||||||
|
method: 'post',
|
||||||
|
data: {users_id: users_id},
|
||||||
|
});
|
||||||
|
}
|
||||||
184
web/src/views/system/role/components/addUsers/crud.tsx
Normal file
184
web/src/views/system/role/components/addUsers/crud.tsx
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
import {getRoleUsersUnauthorized} from './api';
|
||||||
|
import {
|
||||||
|
compute,
|
||||||
|
dict,
|
||||||
|
UserPageQuery,
|
||||||
|
AddReq,
|
||||||
|
DelReq,
|
||||||
|
EditReq,
|
||||||
|
CrudOptions,
|
||||||
|
CreateCrudOptionsProps,
|
||||||
|
CreateCrudOptionsRet
|
||||||
|
} from '@fast-crud/fast-crud';
|
||||||
|
|
||||||
|
import { ref , nextTick} from 'vue';
|
||||||
|
import XEUtils from 'xe-utils';
|
||||||
|
|
||||||
|
export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
|
const pageRequest = async (query: UserPageQuery) => {
|
||||||
|
return await getRoleUsersUnauthorized(query);
|
||||||
|
};
|
||||||
|
const editRequest = async ({ form, row }: EditReq) => {
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
const delRequest = async ({ row }: DelReq) => {
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
const addRequest = async ({ form }: AddReq) => {
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 记录选中的行
|
||||||
|
const selectedRows = ref<any>([]);
|
||||||
|
|
||||||
|
const onSelectionChange = (changed: any) => {
|
||||||
|
const tableData = crudExpose.getTableData();
|
||||||
|
const unChanged = tableData.filter((row: any) => !changed.includes(row));
|
||||||
|
// 添加已选择的行
|
||||||
|
XEUtils.arrayEach(changed, (item: any) => {
|
||||||
|
const ids = XEUtils.pluck(selectedRows.value, 'id');
|
||||||
|
if (!ids.includes(item.id)) {
|
||||||
|
selectedRows.value = XEUtils.union(selectedRows.value, [item]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 剔除未选择的行
|
||||||
|
XEUtils.arrayEach(unChanged, (unItem: any) => {
|
||||||
|
selectedRows.value = XEUtils.remove(selectedRows.value, (item: any) => item.id !== unItem.id);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const toggleRowSelection = () => {
|
||||||
|
// 多选后,回显默认勾选
|
||||||
|
const tableRef = crudExpose.getBaseTableRef();
|
||||||
|
const tableData = crudExpose.getTableData();
|
||||||
|
const selected = XEUtils.filter(tableData, (item: any) => {
|
||||||
|
const ids = XEUtils.pluck(selectedRows.value, 'id');
|
||||||
|
return ids.includes(item.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
XEUtils.arrayEach(selected, (item) => {
|
||||||
|
tableRef.toggleRowSelection(item, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
selectedRows,
|
||||||
|
crudOptions: {
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest,
|
||||||
|
},
|
||||||
|
actionbar: {
|
||||||
|
show: false,
|
||||||
|
buttons: {
|
||||||
|
add: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
show: false,
|
||||||
|
//固定右侧
|
||||||
|
fixed: 'left',
|
||||||
|
width: 150,
|
||||||
|
buttons: {
|
||||||
|
view: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
edit: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
remove: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
rowKey: "id",
|
||||||
|
onSelectionChange,
|
||||||
|
onRefreshed: () => toggleRowSelection(),
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
$checked: {
|
||||||
|
title: "选择",
|
||||||
|
form: { show: false},
|
||||||
|
column: {
|
||||||
|
show: true,
|
||||||
|
type: "selection",
|
||||||
|
align: "center",
|
||||||
|
width: "55px",
|
||||||
|
columnSetDisabled: true, //禁止在列设置中选择
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_index: {
|
||||||
|
title: '序号',
|
||||||
|
form: { show: false },
|
||||||
|
column: {
|
||||||
|
//type: 'index',
|
||||||
|
align: 'center',
|
||||||
|
width: '70px',
|
||||||
|
columnSetDisabled: true, //禁止在列设置中选择
|
||||||
|
formatter: (context) => {
|
||||||
|
//计算序号,你可以自定义计算规则,此处为翻页累加
|
||||||
|
let index = context.index ?? 1;
|
||||||
|
let pagination = crudExpose!.crudBinding.value.pagination;
|
||||||
|
// @ts-ignore
|
||||||
|
return ((pagination.currentPage ?? 1) - 1) * pagination.pageSize + index + 1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
title: '用户名',
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
component: {
|
||||||
|
props: {
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
type: 'text',
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dept: {
|
||||||
|
title: '部门',
|
||||||
|
show: true,
|
||||||
|
type: 'dict-tree',
|
||||||
|
column: {
|
||||||
|
name: 'text',
|
||||||
|
formatter({value,row,index}){
|
||||||
|
return row.dept__name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
disabled: true,
|
||||||
|
col:{span: 6},
|
||||||
|
component: {
|
||||||
|
multiple: false,
|
||||||
|
props: {
|
||||||
|
checkStrictly: true,
|
||||||
|
clearable: true,
|
||||||
|
filterable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
dict: dict({
|
||||||
|
isTree: true,
|
||||||
|
url: '/api/system/dept/all_dept/',
|
||||||
|
value: 'id',
|
||||||
|
label: 'name'
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
91
web/src/views/system/role/components/addUsers/index.vue
Normal file
91
web/src/views/system/role/components/addUsers/index.vue
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog v-model="dialog" title="添加授权用户" direction="rtl" destroy-on-close :before-close="handleDialogClose">
|
||||||
|
<div style="height: 500px;" >
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
<template #pagination-right>
|
||||||
|
<el-popover placement="top" :width="200" trigger="click">
|
||||||
|
<template #reference>
|
||||||
|
<el-button text :type="selectedRowsCount > 0 ? 'primary' : ''">已选中{{ selectedRowsCount }}条数据</el-button>
|
||||||
|
</template>
|
||||||
|
<el-table :data="selectedRows" size="small" :max-height="500">
|
||||||
|
<!-- <el-table-column width="100" property="id" label="id" /> -->
|
||||||
|
<el-table-column width="100" property="name" label="用户名" />
|
||||||
|
<el-table-column fixed="right" label="操作" min-width="50">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button text type="info" :icon="Close" @click="removeSelectedRows(scope.row)" circle />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</fs-crud>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div>
|
||||||
|
<el-button type="primary" @click="handleDialogConfirm"> 确定</el-button>
|
||||||
|
<el-button @click="handleDialogClose"> 取消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
import { useFs } from '@fast-crud/fast-crud';
|
||||||
|
import { createCrudOptions } from './crud';
|
||||||
|
import { successNotification } from '/@/utils/message';
|
||||||
|
import { addRoleUsers } from './api';
|
||||||
|
import { Close } from '@element-plus/icons-vue';
|
||||||
|
import XEUtils from 'xe-utils';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
refreshCallback: {
|
||||||
|
type: Function,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
//对话框是否显示
|
||||||
|
const dialog = ref(false);
|
||||||
|
|
||||||
|
// 父组件刷新回调函数
|
||||||
|
const parentRefreshCallbackFunc = props.refreshCallback;
|
||||||
|
|
||||||
|
//抽屉关闭确认
|
||||||
|
const handleDialogClose = () => {
|
||||||
|
dialog.value = false;
|
||||||
|
selectedRows.value = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDialogConfirm = async () => {
|
||||||
|
if (selectedRows.value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await addRoleUsers(crudRef.value.getSearchFormData().role_id, XEUtils.pluck(selectedRows.value, 'id')).then(res => {
|
||||||
|
successNotification(res.msg);
|
||||||
|
})
|
||||||
|
parentRefreshCallbackFunc && parentRefreshCallbackFunc(); // 刷新父组件
|
||||||
|
handleDialogClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const { crudBinding, crudRef, crudExpose, selectedRows } = useFs({ createCrudOptions, context: {} });
|
||||||
|
const { setSearchFormData, doRefresh } = crudExpose;
|
||||||
|
|
||||||
|
// 选中行的条数
|
||||||
|
const selectedRowsCount = computed(() => {
|
||||||
|
return selectedRows.value.length;
|
||||||
|
});
|
||||||
|
|
||||||
|
const removeSelectedRows = (row: any) => {
|
||||||
|
const tableRef = crudExpose.getBaseTableRef();
|
||||||
|
const tableData = crudExpose.getTableData();
|
||||||
|
if (XEUtils.pluck(tableData, 'id').includes(row.id)) {
|
||||||
|
tableRef.toggleRowSelection(row, false);
|
||||||
|
} else {
|
||||||
|
selectedRows.value = XEUtils.remove(selectedRows.value, (item: any) => item.id !== row.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ dialog, setSearchFormData, doRefresh, parentRefreshCallbackFunc});
|
||||||
|
</script>
|
||||||
44
web/src/views/system/role/components/searchUsers/api.ts
Normal file
44
web/src/views/system/role/components/searchUsers/api.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { request } from '/@/utils/service';
|
||||||
|
import { UserPageQuery} from '@fast-crud/fast-crud';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前角色查询授权的用户
|
||||||
|
* @param query 查询条件 需要有角色id
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getRoleUsersAuthorized(query: UserPageQuery) {
|
||||||
|
query["authorized"] = 1; // 授权的用户
|
||||||
|
return request({
|
||||||
|
url: '/api/system/role/get_role_users/',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 当前角色删除授权的用户
|
||||||
|
* @param role_id 角色id
|
||||||
|
* @param user_id 用户id数组
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function removeRoleUser(role_id: number, user_id: Array<number>) {
|
||||||
|
return request({
|
||||||
|
url: `/api/system/role/${role_id}/remove_role_user/`,
|
||||||
|
method: 'delete',
|
||||||
|
data: {user_id: user_id},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前用户角色添加用户
|
||||||
|
* @param role_id 角色id
|
||||||
|
* @param data 用户id数组
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function addRoleUsers(role_id: number, data: Array<Number>) {
|
||||||
|
return request({
|
||||||
|
url: `/api/system/role/${role_id}/add_role_users/`,
|
||||||
|
method: 'post',
|
||||||
|
data: {users_id: data},
|
||||||
|
});
|
||||||
|
}
|
||||||
193
web/src/views/system/role/components/searchUsers/crud.tsx
Normal file
193
web/src/views/system/role/components/searchUsers/crud.tsx
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
import {getRoleUsersAuthorized, removeRoleUser} from './api';
|
||||||
|
import {
|
||||||
|
compute,
|
||||||
|
dict,
|
||||||
|
UserPageQuery,
|
||||||
|
AddReq,
|
||||||
|
DelReq,
|
||||||
|
EditReq,
|
||||||
|
CrudOptions,
|
||||||
|
CreateCrudOptionsProps,
|
||||||
|
CreateCrudOptionsRet
|
||||||
|
} from '@fast-crud/fast-crud';
|
||||||
|
|
||||||
|
import {auth} from "/@/utils/authFunction";
|
||||||
|
import { ref , nextTick} from 'vue';
|
||||||
|
import XEUtils from 'xe-utils';
|
||||||
|
|
||||||
|
export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
|
const pageRequest = async (query: UserPageQuery) => {
|
||||||
|
return await getRoleUsersAuthorized(query);
|
||||||
|
};
|
||||||
|
const editRequest = async ({ form, row }: EditReq) => {
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
const delRequest = async ({ row }: DelReq) => {
|
||||||
|
return await removeRoleUser(crudExpose.crudRef.value.getSearchFormData().role_id, [row.id]);
|
||||||
|
};
|
||||||
|
const addRequest = async ({ form }: AddReq) => {
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 记录选中的行
|
||||||
|
const selectedRows = ref<any>([]);
|
||||||
|
|
||||||
|
const onSelectionChange = (changed: any) => {
|
||||||
|
const tableData = crudExpose.getTableData();
|
||||||
|
const unChanged = tableData.filter((row: any) => !changed.includes(row));
|
||||||
|
// 添加已选择的行
|
||||||
|
XEUtils.arrayEach(changed, (item: any) => {
|
||||||
|
const ids = XEUtils.pluck(selectedRows.value, 'id');
|
||||||
|
if (!ids.includes(item.id)) {
|
||||||
|
selectedRows.value = XEUtils.union(selectedRows.value, [item]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 剔除未选择的行
|
||||||
|
XEUtils.arrayEach(unChanged, (unItem: any) => {
|
||||||
|
selectedRows.value = XEUtils.remove(selectedRows.value, (item: any) => item.id !== unItem.id);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const toggleRowSelection = () => {
|
||||||
|
// 多选后,回显默认勾选
|
||||||
|
const tableRef = crudExpose.getBaseTableRef();
|
||||||
|
const tableData = crudExpose.getTableData();
|
||||||
|
const selected = XEUtils.filter(tableData, (item: any) => {
|
||||||
|
const ids = XEUtils.pluck(selectedRows.value, 'id');
|
||||||
|
return ids.includes(item.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
XEUtils.arrayEach(selected, (item) => {
|
||||||
|
tableRef.toggleRowSelection(item, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
selectedRows,
|
||||||
|
crudOptions: {
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest,
|
||||||
|
},
|
||||||
|
actionbar: {
|
||||||
|
buttons: {
|
||||||
|
add: {
|
||||||
|
show: auth('role:AuthorizedAdd'),
|
||||||
|
click: (ctx: any) => {
|
||||||
|
context!.subUserRef.value.dialog = true;
|
||||||
|
nextTick(() => {
|
||||||
|
context!.subUserRef.value.setSearchFormData({ form: { role_id: crudExpose.crudRef.value.getSearchFormData().role_id } });
|
||||||
|
context!.subUserRef.value.doRefresh();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
//固定右侧
|
||||||
|
fixed: 'left',
|
||||||
|
width: 120,
|
||||||
|
show: auth('role:AuthorizedDel'),
|
||||||
|
buttons: {
|
||||||
|
view: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
edit: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
remove: {
|
||||||
|
iconRight: 'Delete',
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
rowKey: "id",
|
||||||
|
onSelectionChange,
|
||||||
|
onRefreshed: () => toggleRowSelection(),
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
$checked: {
|
||||||
|
title: "选择",
|
||||||
|
form: { show: false},
|
||||||
|
column: {
|
||||||
|
show: auth('role:AuthorizedDel'),
|
||||||
|
type: "selection",
|
||||||
|
align: "center",
|
||||||
|
width: "55px",
|
||||||
|
columnSetDisabled: true, //禁止在列设置中选择
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_index: {
|
||||||
|
title: '序号',
|
||||||
|
form: { show: false },
|
||||||
|
column: {
|
||||||
|
//type: 'index',
|
||||||
|
align: 'center',
|
||||||
|
width: '70px',
|
||||||
|
columnSetDisabled: true, //禁止在列设置中选择
|
||||||
|
formatter: (context) => {
|
||||||
|
//计算序号,你可以自定义计算规则,此处为翻页累加
|
||||||
|
let index = context.index ?? 1;
|
||||||
|
let pagination = crudExpose!.crudBinding.value.pagination;
|
||||||
|
// @ts-ignore
|
||||||
|
return ((pagination.currentPage ?? 1) - 1) * pagination.pageSize + index + 1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
title: '用户名',
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
component: {
|
||||||
|
props: {
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
type: 'text',
|
||||||
|
form: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dept: {
|
||||||
|
title: '部门',
|
||||||
|
show: true,
|
||||||
|
type: 'dict-tree',
|
||||||
|
column: {
|
||||||
|
name: 'text',
|
||||||
|
formatter({value,row,index}){
|
||||||
|
return row.dept__name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
show: true,
|
||||||
|
disabled: true,
|
||||||
|
col:{span: 6},
|
||||||
|
component: {
|
||||||
|
multiple: false,
|
||||||
|
props: {
|
||||||
|
checkStrictly: true,
|
||||||
|
clearable: true,
|
||||||
|
filterable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
dict: dict({
|
||||||
|
isTree: true,
|
||||||
|
url: '/api/system/dept/all_dept/',
|
||||||
|
value: 'id',
|
||||||
|
label: 'name'
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
98
web/src/views/system/role/components/searchUsers/index.vue
Normal file
98
web/src/views/system/role/components/searchUsers/index.vue
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer size="70%" v-model="RoleUserDrawer.drawerVisible" direction="rtl" destroy-on-close :before-close="handleClose">
|
||||||
|
<template #header>
|
||||||
|
<div>
|
||||||
|
当前授权角色:
|
||||||
|
<el-tag>{{ RoleUserDrawer.role_name }}</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
<template #pagination-right>
|
||||||
|
<el-popover placement="top" :width="200" trigger="click">
|
||||||
|
<template #reference>
|
||||||
|
<el-button text :type="selectedRowsCount > 0 ? 'primary' : ''">已选中{{ selectedRowsCount }}条数据</el-button>
|
||||||
|
</template>
|
||||||
|
<el-table :data="selectedRows" size="small" :max-height="500" >
|
||||||
|
<!-- <el-table-column width="100" property="id" label="id" /> -->
|
||||||
|
<el-table-column width="100" property="name" label="用户名" />
|
||||||
|
<el-table-column fixed="right" label="操作" min-width="60">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button text type="info" :icon="Close" @click="removeSelectedRows(scope.row)" circle />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
<template #pagination-left>
|
||||||
|
<el-tooltip content="批量删除所选择的用户权限">
|
||||||
|
<el-button v-show="selectedRowsCount > 0 && auth('role:AuthorizedDel')" type="danger" @click="multipleDel" :icon="Delete">批量删除</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</fs-crud>
|
||||||
|
<subUser ref="subUserRef" :refreshCallback="refreshData"> </subUser>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {auth} from "/@/utils/authFunction";
|
||||||
|
import { ref, onMounted, defineAsyncComponent, computed } from 'vue';
|
||||||
|
import { useFs } from '@fast-crud/fast-crud';
|
||||||
|
import { createCrudOptions } from './crud';
|
||||||
|
import { Close, Delete } from '@element-plus/icons-vue';
|
||||||
|
import XEUtils from 'xe-utils';
|
||||||
|
import {removeRoleUser} from "./api"
|
||||||
|
import { ElMessageBox } from 'element-plus';
|
||||||
|
import { errorMessage, successNotification } from '/@/utils/message';
|
||||||
|
|
||||||
|
import { RoleUserStores } from '../../stores/RoleUserStores';
|
||||||
|
const RoleUserDrawer = RoleUserStores(); // 授权用户抽屉参数
|
||||||
|
|
||||||
|
const subUser = defineAsyncComponent(() => import('../addUsers/index.vue'));
|
||||||
|
const subUserRef = ref();
|
||||||
|
|
||||||
|
const refreshData = () => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
//抽屉是否显示
|
||||||
|
const drawer = ref(false);
|
||||||
|
|
||||||
|
//抽屉关闭确认
|
||||||
|
const handleClose = (done: () => void) => {
|
||||||
|
selectedRows.value = [];
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选中行的条数
|
||||||
|
const selectedRowsCount = computed(() => {
|
||||||
|
return selectedRows.value.length;
|
||||||
|
});
|
||||||
|
|
||||||
|
const removeSelectedRows = (row: any) => {
|
||||||
|
const tableRef = crudExpose.getBaseTableRef();
|
||||||
|
const tableData = crudExpose.getTableData();
|
||||||
|
if (XEUtils.pluck(tableData, 'id').includes(row.id)) {
|
||||||
|
tableRef.toggleRowSelection(row, false);
|
||||||
|
} else {
|
||||||
|
selectedRows.value = XEUtils.remove(selectedRows.value, (item: any) => item.id !== row.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const multipleDel = async () => {
|
||||||
|
if (selectedRows.value.length < 1) {
|
||||||
|
errorMessage("请先勾选用户");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await ElMessageBox.confirm(`确定要删除这 “${selectedRows.value.length}” 位用户的权限吗`, "确认");
|
||||||
|
const req = await removeRoleUser(crudRef.value.getSearchFormData().role_id, XEUtils.pluck(selectedRows.value, 'id'));
|
||||||
|
selectedRows.value = [];
|
||||||
|
successNotification(req.msg)
|
||||||
|
crudExpose.doRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
const { crudBinding, crudRef, crudExpose, selectedRows } = useFs({ createCrudOptions, context: {subUserRef} });
|
||||||
|
const { setSearchFormData, doRefresh } = crudExpose;
|
||||||
|
|
||||||
|
defineExpose({ drawer, setSearchFormData, doRefresh });
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -3,6 +3,7 @@ import * as api from './api';
|
|||||||
import { dictionary } from '/@/utils/dictionary';
|
import { dictionary } from '/@/utils/dictionary';
|
||||||
import { successMessage } from '../../../utils/message';
|
import { successMessage } from '../../../utils/message';
|
||||||
import { auth } from '/@/utils/authFunction';
|
import { auth } from '/@/utils/authFunction';
|
||||||
|
import { nextTick, computed } from 'vue';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -46,7 +47,12 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
|
|||||||
rowHandle: {
|
rowHandle: {
|
||||||
//固定右侧
|
//固定右侧
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 320,
|
width: computed(() => {
|
||||||
|
if (auth('role:AuthorizedAdd') || auth('role:AuthorizedSearch')){
|
||||||
|
return 420;
|
||||||
|
}
|
||||||
|
return 320;
|
||||||
|
}),
|
||||||
buttons: {
|
buttons: {
|
||||||
view: {
|
view: {
|
||||||
show: true,
|
show: true,
|
||||||
@@ -57,6 +63,19 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
|
|||||||
remove: {
|
remove: {
|
||||||
show: auth('role:Delete'),
|
show: auth('role:Delete'),
|
||||||
},
|
},
|
||||||
|
assignment: {
|
||||||
|
type: 'primary',
|
||||||
|
text: '授权用户',
|
||||||
|
show: auth('role:AuthorizedAdd') || auth('role:AuthorizedSearch'),
|
||||||
|
click: (ctx: any) => {
|
||||||
|
const { row } = ctx;
|
||||||
|
context!.RoleUserDrawer.handleDrawerOpen(row);
|
||||||
|
nextTick(() => {
|
||||||
|
context!.RoleUserRef.value.setSearchFormData({ form: { role_id: row.id } });
|
||||||
|
context!.RoleUserRef.value.doRefresh();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
permission: {
|
permission: {
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
text: '权限配置',
|
text: '权限配置',
|
||||||
|
|||||||
@@ -2,17 +2,22 @@
|
|||||||
<fs-page>
|
<fs-page>
|
||||||
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||||
<PermissionDrawerCom />
|
<PermissionDrawerCom />
|
||||||
|
<RoleUser ref="RoleUserRef" />
|
||||||
</fs-page>
|
</fs-page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="role">
|
<script lang="ts" setup name="role">
|
||||||
import { defineAsyncComponent, onMounted } from 'vue';
|
import { defineAsyncComponent, onMounted, ref} from 'vue';
|
||||||
import { useFs } from '@fast-crud/fast-crud';
|
import { useFs } from '@fast-crud/fast-crud';
|
||||||
import { createCrudOptions } from './crud';
|
import { createCrudOptions } from './crud';
|
||||||
import { RoleDrawerStores } from './stores/RoleDrawerStores';
|
import { RoleDrawerStores } from './stores/RoleDrawerStores';
|
||||||
import { RoleMenuBtnStores } from './stores/RoleMenuBtnStores';
|
import { RoleMenuBtnStores } from './stores/RoleMenuBtnStores';
|
||||||
import { RoleMenuFieldStores } from './stores/RoleMenuFieldStores';
|
import { RoleMenuFieldStores } from './stores/RoleMenuFieldStores';
|
||||||
import { RoleUsersStores } from './stores/RoleUsersStores';
|
import { RoleUsersStores } from './stores/RoleUsersStores';
|
||||||
|
import { RoleUserStores } from './stores/RoleUserStores';
|
||||||
|
|
||||||
|
const RoleUser = defineAsyncComponent(() => import('./components/searchUsers/index.vue'));
|
||||||
|
const RoleUserRef = ref();
|
||||||
|
|
||||||
const PermissionDrawerCom = defineAsyncComponent(() => import('./components/RoleDrawer.vue'));
|
const PermissionDrawerCom = defineAsyncComponent(() => import('./components/RoleDrawer.vue'));
|
||||||
|
|
||||||
@@ -20,9 +25,11 @@ const RoleDrawer = RoleDrawerStores(); // 角色-抽屉
|
|||||||
const RoleMenuBtn = RoleMenuBtnStores(); // 角色-菜单
|
const RoleMenuBtn = RoleMenuBtnStores(); // 角色-菜单
|
||||||
const RoleMenuField = RoleMenuFieldStores();// 角色-菜单-字段
|
const RoleMenuField = RoleMenuFieldStores();// 角色-菜单-字段
|
||||||
const RoleUsers = RoleUsersStores();// 角色-用户
|
const RoleUsers = RoleUsersStores();// 角色-用户
|
||||||
|
const RoleUserDrawer = RoleUserStores(); // 授权用户抽屉参数
|
||||||
|
|
||||||
const { crudBinding, crudRef, crudExpose } = useFs({
|
const { crudBinding, crudRef, crudExpose } = useFs({
|
||||||
createCrudOptions,
|
createCrudOptions,
|
||||||
context: { RoleDrawer, RoleMenuBtn, RoleMenuField },
|
context: { RoleDrawer, RoleMenuBtn, RoleMenuField, RoleUserDrawer, RoleUserRef },
|
||||||
});
|
});
|
||||||
|
|
||||||
// 页面打开后获取列表数据
|
// 页面打开后获取列表数据
|
||||||
|
|||||||
29
web/src/views/system/role/stores/RoleUserStores.ts
Normal file
29
web/src/views/system/role/stores/RoleUserStores.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限抽屉:角色-用户
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const RoleUserStores = defineStore('RoleUserStores', {
|
||||||
|
state: (): any => ({
|
||||||
|
drawerVisible: false,
|
||||||
|
role_id: undefined,
|
||||||
|
role_name: undefined,
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
/**
|
||||||
|
* 打开权限修改抽屉
|
||||||
|
*/
|
||||||
|
handleDrawerOpen(row: any) {
|
||||||
|
this.drawerVisible = true;
|
||||||
|
this.role_name = row.name;
|
||||||
|
this.role_id = row.id;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 关闭权限修改抽屉
|
||||||
|
*/
|
||||||
|
handleDrawerClose() {
|
||||||
|
this.drawerVisible = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user