diff --git a/dvadmin-backend/apps/permission/filters.py b/dvadmin-backend/apps/permission/filters.py index 4e51d35..8e9be06 100644 --- a/dvadmin-backend/apps/permission/filters.py +++ b/dvadmin-backend/apps/permission/filters.py @@ -47,7 +47,7 @@ class UserProfileFilter(django_filters.rest_framework.FilterSet): """ 用户管理 简单序过滤器 """ - + deptId = django_filters.CharFilter(field_name='dept__id') class Meta: model = UserProfile exclude = ('secret', 'password',) diff --git a/dvadmin-backend/apps/permission/models/users.py b/dvadmin-backend/apps/permission/models/users.py index 7733482..ba44234 100644 --- a/dvadmin-backend/apps/permission/models/users.py +++ b/dvadmin-backend/apps/permission/models/users.py @@ -21,7 +21,7 @@ class UserProfile(AbstractUser): secret = CharField(max_length=255, default=uuid4, verbose_name='加密秘钥') email = CharField(max_length=255, verbose_name="邮箱", null=True) mobile = CharField(max_length=255, verbose_name="电话", null=True) - avatar = TextField(verbose_name="头像") + avatar = TextField(verbose_name="头像",null=True) name = CharField(max_length=40, verbose_name="姓名") gender = IntegerField(default=2, choices=GENDER_CHOICES, verbose_name="性别") remark = TextField(verbose_name="备注", null=True) diff --git a/dvadmin-backend/apps/permission/serializers.py b/dvadmin-backend/apps/permission/serializers.py index e594281..db490b3 100644 --- a/dvadmin-backend/apps/permission/serializers.py +++ b/dvadmin-backend/apps/permission/serializers.py @@ -1,32 +1,10 @@ from rest_framework import serializers +from rest_framework.validators import UniqueValidator from apps.op_drf.serializers import CustomModelSerializer from apps.permission.models import Menu, Dept, Post, Role, UserProfile -# ================================================= # -# ************** 用户管理 序列化器 ************** # -# ================================================= # - - -class UserProfileSerializer(CustomModelSerializer): - """ - 简单用户序列化器 - """ - admin = serializers.SerializerMethodField(read_only=True) - - def get_admin(self, obj: UserProfile): - role_list = obj.role.all().values_list('admin', flat=True) - if True in list(set(role_list)): - return True - return False - - class Meta: - model = UserProfile - dept = 2 - exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined') - - # ================================================= # # ************** 菜单管理 序列化器 ************** # # ================================================= # @@ -131,6 +109,16 @@ class PostSerializer(CustomModelSerializer): exclude = ('description', 'creator', 'modifier') +class PostSimpleSerializer(CustomModelSerializer): + """ + 岗位管理 极简单序列化器 + """ + + class Meta: + model = Post + fields = ('id', 'postName', 'postCode', 'status') + + class PostCreateUpdateSerializer(CustomModelSerializer): """ 岗位管理 创建/更新时的列化器 @@ -159,6 +147,16 @@ class RoleSerializer(CustomModelSerializer): exclude = ('description', 'creator', 'modifier') +class RoleSimpleSerializer(CustomModelSerializer): + """ + 角色管理 极简单序列化器 + """ + + class Meta: + model = Role + fields = ('id', 'roleName', 'roleKey', 'status') + + class RoleCreateUpdateSerializer(CustomModelSerializer): """ 角色管理 创建/更新时的列化器 @@ -179,3 +177,66 @@ class RoleCreateUpdateSerializer(CustomModelSerializer): model = Role exclude = ('description', 'creator', 'modifier') read_only_fields = ('update_datetime', 'create_datetime', 'creator', 'modifier') + + +# ================================================= # +# ************** 用户管理 序列化器 ************** # +# ================================================= # + + +class UserProfileSerializer(CustomModelSerializer): + """ + 简单用户序列化器 + """ + admin = serializers.SerializerMethodField(read_only=True) + deptId = serializers.IntegerField(source='dept.id',read_only=True) + + def get_admin(self, obj: UserProfile): + role_list = obj.role.all().values_list('admin', flat=True) + if True in list(set(role_list)): + return True + return False + + class Meta: + model = UserProfile + depth = 1 + exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined') + + +class UserProfileCreateUpdateSerializer(CustomModelSerializer): + """ + 用户管理 创建/更新时的列化器 + """ + admin = serializers.SerializerMethodField(read_only=True) + post = PostSerializer(many=True, read_only=True) + role = RoleSerializer(many=True, read_only=True) + username = serializers.CharField(required=True, max_length=150, + validators=[UniqueValidator(queryset=UserProfile.objects.all(), message="用戶已存在")], + error_messages={ + "blank":"请输入用户名称", + "required":"用户名称不能为空", + "max_length":"用户名称过长", + }) + def get_admin(self, obj: UserProfile): + role_list = obj.role.all().values_list('admin', flat=True) + if True in list(set(role_list)): + return True + return False + + def validate(self, attrs: dict): + + return super().validate(attrs) + + def save(self, **kwargs): + self.validated_data['dept_id'] = self.initial_data.get('deptId',None) + data = super().save(**kwargs) + data.set_password(self.initial_data.get('password',None)) + data.save() + data.post.set(self.initial_data.get('postIds')) + data.role.set(self.initial_data.get('roleIds')) + return data + + class Meta: + model = UserProfile + exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined') + read_only_fields = ('dept',) diff --git a/dvadmin-backend/apps/permission/urls.py b/dvadmin-backend/apps/permission/urls.py index 09a3954..4ff7cb0 100644 --- a/dvadmin-backend/apps/permission/urls.py +++ b/dvadmin-backend/apps/permission/urls.py @@ -1,7 +1,8 @@ from django.urls import re_path from rest_framework.routers import DefaultRouter -from apps.permission.views import MenuModelViewSet, DeptModelViewSet, PostModelViewSet, RoleModelViewSet +from apps.permission.views import MenuModelViewSet, DeptModelViewSet, PostModelViewSet, RoleModelViewSet, \ + UserProfileModelViewSet router = DefaultRouter() router.register(r'menus', MenuModelViewSet) @@ -9,6 +10,7 @@ router.register(r'dept', DeptModelViewSet) router.register(r'dept/exclude', DeptModelViewSet) router.register(r'post', PostModelViewSet) router.register(r'role', RoleModelViewSet) +router.register(r'user', UserProfileModelViewSet) urlpatterns = [ re_path('dept/exclude/(?P.*)/', DeptModelViewSet.as_view({'get': 'exclude_list'})), @@ -18,6 +20,11 @@ urlpatterns = [ re_path('menus/roleMenuTreeselect/(?P.*)/', MenuModelViewSet.as_view({'get': 'role_menu_tree_select'})), # 根据角色ID查询部门树结构 re_path('dept/roleDeptTreeselect/(?P.*)/', DeptModelViewSet.as_view({'get': 'role_dept_tree_select'})), + # 更新状态 + re_path('user/changeStatus/', UserProfileModelViewSet.as_view({'put': 'change_status'})), + # 获取用户详情 + re_path('user/details/', UserProfileModelViewSet.as_view({'get': 'get_user_details'})), + re_path('user/resetPwd/', UserProfileModelViewSet.as_view({'put': 'reset_pwd'})), ] urlpatterns += router.urls diff --git a/dvadmin-backend/apps/permission/views.py b/dvadmin-backend/apps/permission/views.py index ec45fac..a2c0e26 100644 --- a/dvadmin-backend/apps/permission/views.py +++ b/dvadmin-backend/apps/permission/views.py @@ -5,11 +5,12 @@ from rest_framework.response import Response from rest_framework.views import APIView from apps.op_drf.viewsets import CustomModelViewSet -from apps.permission.filters import MenuFilter, DeptFilter, PostFilter, RoleFilter -from apps.permission.models import Role, Menu, Dept, Post +from apps.permission.filters import MenuFilter, DeptFilter, PostFilter, RoleFilter, UserProfileFilter +from apps.permission.models import Role, Menu, Dept, Post, UserProfile from apps.permission.serializers import UserProfileSerializer, MenuSerializer, RoleSerializer, \ MenuCreateUpdateSerializer, DeptSerializer, DeptCreateUpdateSerializer, PostSerializer, PostCreateUpdateSerializer, \ - RoleCreateUpdateSerializer, DeptTreeSerializer, MenuTreeSerializer + RoleCreateUpdateSerializer, DeptTreeSerializer, MenuTreeSerializer, UserProfileCreateUpdateSerializer, \ + PostSimpleSerializer, RoleSimpleSerializer from utils.response import SuccessResponse @@ -184,3 +185,74 @@ class RoleModelViewSet(CustomModelViewSet): # create_extra_permission_classes = (IsManagerPermission,) search_fields = ('roleName',) ordering = 'create_datetime' # 默认排序 + + +class UserProfileModelViewSet(CustomModelViewSet): + """ + 用户管理 的CRUD视图 + """ + queryset = UserProfile.objects.all() + serializer_class = UserProfileSerializer + create_serializer_class = UserProfileCreateUpdateSerializer + update_serializer_class = UserProfileCreateUpdateSerializer + filter_class = UserProfileFilter + # update_extra_permission_classes = (IsManagerPermission,) + # destroy_extra_permission_classes = (IsManagerPermission,) + # create_extra_permission_classes = (IsManagerPermission,) + search_fields = ('username',) + ordering = 'create_datetime' # 默认排序 + + def change_status(self, request: Request, *args, **kwargs): + """ + 修改用户状态 + :param request: + :param args: + :param kwargs: + :return: + """ + instance = self.queryset.get(id=request.data.get('userId')) + instance.is_active = request.data.get('status') + instance.save() + serializer = self.get_serializer(instance) + if hasattr(self, 'handle_logging'): + self.handle_logging(request, instance=instance, *args, **kwargs) + return SuccessResponse(serializer.data) + + def get_user_details(self, request: Request, *args, **kwargs): + """ + 获取用户详情 + :param request: + :param args: + :param kwargs: + :return: + """ + userId = request.query_params.get('userId') + data = { + 'posts': PostSimpleSerializer(Post.objects.all().order_by('postSort'), many=True).data, + 'roles': RoleSimpleSerializer(Role.objects.all().order_by('roleSort'), many=True).data + } + if userId: + instance = self.queryset.get(id=userId) + serializer = self.get_serializer(instance) + data['data'] = serializer.data + data['postIds'] = [ele.get('id') for ele in serializer.data.get('post')] + data['roleIds'] = [ele.get('id') for ele in serializer.data.get('role')] + if hasattr(self, 'handle_logging'): + self.handle_logging(request, instance=instance, *args, **kwargs) + return SuccessResponse(data) + + def reset_pwd(self, request: Request, *args, **kwargs): + """ + 重置密码 + :param request: + :param args: + :param kwargs: + :return: + """ + instance = self.queryset.get(id=request.data.get('userId')) + serializer = self.get_serializer(instance) + instance.set_password(request.data.get('password')) + instance.save() + if hasattr(self, 'handle_logging'): + self.handle_logging(request, instance=instance, *args,**kwargs) + return SuccessResponse(serializer.data) diff --git a/dvadmin-ui/src/api/permission/user.js b/dvadmin-ui/src/api/permission/user.js index 3b9a776..91e5219 100755 --- a/dvadmin-ui/src/api/permission/user.js +++ b/dvadmin-ui/src/api/permission/user.js @@ -1,10 +1,10 @@ import request from '@/utils/request' -import { praseStrEmpty } from "@/utils/ruoyi"; +import {praseStrEmpty} from "@/utils/ruoyi"; // 查询用户列表 export function listUser(query) { return request({ - url: '/system/user/list', + url: '/permission/user/', method: 'get', params: query }) @@ -13,7 +13,7 @@ export function listUser(query) { // 查询用户详细 export function getUser(userId) { return request({ - url: '/system/user/' + praseStrEmpty(userId), + url: '/permission/user/details/?userId=' + praseStrEmpty(userId) , method: 'get' }) } @@ -21,7 +21,7 @@ export function getUser(userId) { // 新增用户 export function addUser(data) { return request({ - url: '/system/user', + url: '/permission/user/', method: 'post', data: data }) @@ -30,7 +30,7 @@ export function addUser(data) { // 修改用户 export function updateUser(data) { return request({ - url: '/system/user', + url: '/permission/user/' + data.id + '/', method: 'put', data: data }) @@ -39,7 +39,7 @@ export function updateUser(data) { // 删除用户 export function delUser(userId) { return request({ - url: '/system/user/' + userId, + url: '/permission/user/' + userId + '/', method: 'delete' }) } @@ -47,7 +47,7 @@ export function delUser(userId) { // 导出用户 export function exportUser(query) { return request({ - url: '/system/user/export', + url: '/permission/user/export/', method: 'get', params: query }) @@ -60,7 +60,7 @@ export function resetUserPwd(userId, password) { password } return request({ - url: '/system/user/resetPwd', + url: '/permission/user/resetPwd/', method: 'put', data: data }) @@ -73,7 +73,7 @@ export function changeUserStatus(userId, status) { status } return request({ - url: '/system/user/changeStatus', + url: '/permission/user/changeStatus/', method: 'put', data: data }) @@ -82,7 +82,7 @@ export function changeUserStatus(userId, status) { // 查询用户个人信息 export function getUserProfile() { return request({ - url: '/system/user/profile', + url: '/permission/user/profile/', method: 'get' }) } @@ -90,7 +90,7 @@ export function getUserProfile() { // 修改用户个人信息 export function updateUserProfile(data) { return request({ - url: '/system/user/profile', + url: '/permission/user/profile', method: 'put', data: data }) @@ -103,7 +103,7 @@ export function updateUserPwd(oldPassword, newPassword) { newPassword } return request({ - url: '/system/user/profile/updatePwd', + url: '/permission/user/profile/updatePwd/', method: 'put', params: data }) @@ -112,7 +112,7 @@ export function updateUserPwd(oldPassword, newPassword) { // 用户头像上传 export function uploadAvatar(data) { return request({ - url: '/system/user/profile/avatar', + url: '/permission/user/profile/avatar', method: 'post', data: data }) @@ -121,7 +121,7 @@ export function uploadAvatar(data) { // 下载用户导入模板 export function importTemplate() { return request({ - url: '/system/user/importTemplate', + url: '/permission/user/importTemplate', method: 'get' }) } diff --git a/dvadmin-ui/src/views/permission/user/index.vue b/dvadmin-ui/src/views/permission/user/index.vue index 31b9104..024a3a2 100755 --- a/dvadmin-ui/src/views/permission/user/index.vue +++ b/dvadmin-ui/src/views/permission/user/index.vue @@ -28,9 +28,9 @@ - + - + - + - + - - - + + + - - + + @@ -175,7 +173,7 @@ v-hasPermi="['system:user:edit']" >修改 - - + + @@ -220,8 +218,8 @@ - - + + @@ -232,12 +230,12 @@ - - + + - + @@ -257,7 +255,7 @@ - + @@ -286,9 +284,9 @@ @@ -381,7 +379,7 @@ export default { // 日期范围 dateRange: [], // 状态数据字典 - statusOptions: [], + statusOptions: [{dictLabel: '正常', dictValue: true,}, {dictLabel: '停用', dictValue: false,}], // 性别状态字典 sexOptions: [], // 岗位选项 @@ -413,9 +411,9 @@ export default { queryParams: { pageNum: 1, pageSize: 10, - userName: undefined, - phonenumber: undefined, - status: undefined, + username: undefined, + mobile: undefined, + is_active: undefined, deptId: undefined }, // 列信息 @@ -430,10 +428,10 @@ export default { ], // 表单校验 rules: { - userName: [ + username: [ { required: true, message: "用户名称不能为空", trigger: "blur" } ], - nickName: [ + name: [ { required: true, message: "用户昵称不能为空", trigger: "blur" } ], password: [ @@ -446,7 +444,7 @@ export default { trigger: ["blur", "change"] } ], - phonenumber: [ + mobile: [ { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", @@ -465,9 +463,9 @@ export default { created() { this.getList(); this.getTreeselect(); - this.getDicts("sys_normal_disable").then(response => { - this.statusOptions = response.data; - }); + // this.getDicts("sys_normal_disable").then(response => { + // this.statusOptions = response.data; + // }); this.getDicts("sys_user_sex").then(response => { this.sexOptions = response.data; }); @@ -480,8 +478,8 @@ export default { getList() { this.loading = true; listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => { - this.userList = response.rows; - this.total = response.total; + this.userList = response.data.results; + this.total = response.data.count; this.loading = false; } ); @@ -489,7 +487,7 @@ export default { /** 查询部门下拉树结构 */ getTreeselect() { treeselect().then(response => { - this.deptOptions = response.data; + this.deptOptions = this.handleTree(response.data,'id'); }); }, // 筛选节点 @@ -504,17 +502,17 @@ export default { }, // 用户状态修改 handleStatusChange(row) { - let text = row.status === "0" ? "启用" : "停用"; - this.$confirm('确认要"' + text + '""' + row.userName + '"用户吗?', "警告", { + let text = row.is_active === true ? "启用" : "停用"; + this.$confirm('确认要"' + text + '""' + row.username + '"用户吗?', "警告", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }).then(function() { - return changeUserStatus(row.userId, row.status); + return changeUserStatus(row.id, row.is_active); }).then(() => { this.msgSuccess(text + "成功"); }).catch(function() { - row.status = row.status === "0" ? "1" : "0"; + row.is_active = row.is_active === false ? true : false; }); }, // 取消按钮 @@ -525,15 +523,15 @@ export default { // 表单重置 reset() { this.form = { - userId: undefined, + id: undefined, deptId: undefined, - userName: undefined, - nickName: undefined, + username: undefined, + name: undefined, password: undefined, - phonenumber: undefined, + mobile: undefined, email: undefined, sex: undefined, - status: "0", + is_active: false, remark: undefined, postIds: [], roleIds: [] @@ -548,12 +546,13 @@ export default { /** 重置按钮操作 */ resetQuery() { this.dateRange = []; + this.queryParams.deptId = '' this.resetForm("queryForm"); this.handleQuery(); }, // 多选框选中数据 handleSelectionChange(selection) { - this.ids = selection.map(item => item.userId); + this.ids = selection.map(item => item.id); this.single = selection.length != 1; this.multiple = !selection.length; }, @@ -562,8 +561,8 @@ export default { this.reset(); this.getTreeselect(); getUser().then(response => { - this.postOptions = response.posts; - this.roleOptions = response.roles; + this.postOptions = response.data.posts; + this.roleOptions = response.data.roles; this.open = true; this.title = "添加用户"; this.form.password = this.initPassword; @@ -573,13 +572,13 @@ export default { handleUpdate(row) { this.reset(); this.getTreeselect(); - const userId = row.userId || this.ids; - getUser(userId).then(response => { - this.form = response.data; - this.postOptions = response.posts; - this.roleOptions = response.roles; - this.form.postIds = response.postIds; - this.form.roleIds = response.roleIds; + const id = row.id || this.ids; + getUser(id).then(response => { + this.form = response.data.data; + this.postOptions = response.data.posts; + this.roleOptions = response.data.roles; + this.form.postIds = response.data.postIds; + this.form.roleIds = response.data.roleIds; this.open = true; this.title = "修改用户"; this.form.password = ""; @@ -587,11 +586,11 @@ export default { }, /** 重置密码按钮操作 */ handleResetPwd(row) { - this.$prompt('请输入"' + row.userName + '"的新密码', "提示", { + this.$prompt('请输入"' + row.username + '"的新密码', "提示", { confirmButtonText: "确定", cancelButtonText: "取消" }).then(({ value }) => { - resetUserPwd(row.userId, value).then(response => { + resetUserPwd(row.id, value).then(response => { this.msgSuccess("修改成功,新密码是:" + value); }); }).catch(() => {}); @@ -600,7 +599,7 @@ export default { submitForm: function() { this.$refs["form"].validate(valid => { if (valid) { - if (this.form.userId != undefined) { + if (this.form.id != undefined) { updateUser(this.form).then(response => { this.msgSuccess("修改成功"); this.open = false; @@ -618,7 +617,7 @@ export default { }, /** 删除按钮操作 */ handleDelete(row) { - const userIds = row.userId || this.ids; + const userIds = row.id || this.ids; this.$confirm('是否确认删除用户编号为"' + userIds + '"的数据项?', "警告", { confirmButtonText: "确定", cancelButtonText: "取消",