!81 优化用户信息

Merge pull request !81 from dvadmin/v2.x
pull/82/MERGE
dvadmin 2022-11-27 13:31:53 +00:00 committed by Gitee
commit 63427b25d8
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
8 changed files with 122 additions and 82 deletions

View File

@ -5,7 +5,7 @@ from django_restql.fields import DynamicSerializerMethodField
from rest_framework import serializers
from rest_framework.decorators import action, permission_classes
from rest_framework.permissions import IsAuthenticated
from django.db import connection
from application import dispatch
from dvadmin.system.models import Users, Role, Dept
from dvadmin.system.views.role import RoleSerializer
@ -15,17 +15,18 @@ from dvadmin.utils.validator import CustomUniqueValidator
from dvadmin.utils.viewset import CustomModelViewSet
def recursion(instance,parent,result):
new_instance = getattr(instance,parent,None)
def recursion(instance, parent, result):
new_instance = getattr(instance, parent, None)
res = []
data = getattr(instance, result, None)
if data:
res.append(data)
if new_instance:
array = recursion(new_instance,parent,result)
res+=(array)
array = recursion(new_instance, parent, result)
res += (array)
return res
class UserSerializer(CustomModelSerializer):
"""
用户管理-序列化器
@ -63,12 +64,13 @@ class UsersInitSerializer(CustomModelSerializer):
"""
初始化获取数信息(用于生成初始化json文件)
"""
def save(self, **kwargs):
instance = super().save(**kwargs)
role_key = self.initial_data.get('role_key',[])
role_ids = Role.objects.filter(key__in=role_key).values_list('id',flat=True)
role_key = self.initial_data.get('role_key', [])
role_ids = Role.objects.filter(key__in=role_key).values_list('id', flat=True)
instance.role.set(role_ids)
dept_key = self.initial_data.get('dept_key',None)
dept_key = self.initial_data.get('dept_key', None)
dept_id = Dept.objects.filter(key=dept_key).first()
instance.dept = dept_id
instance.save()
@ -162,6 +164,29 @@ class UserUpdateSerializer(CustomModelSerializer):
}
class UserInfoUpdateSerializer(CustomModelSerializer):
"""
用户修改-序列化器
"""
mobile = serializers.CharField(
max_length=50,
validators=[
CustomUniqueValidator(queryset=Users.objects.all(), message="手机号必须唯一")
],
allow_blank=True
)
def update(self, instance, validated_data):
return super().update(instance, validated_data)
class Meta:
model = Users
fields = ['email', 'mobile', 'avatar', 'name', 'gender']
extra_kwargs = {
"post": {"required": False, "read_only": True},
}
class ExportUserProfileSerializer(CustomModelSerializer):
"""
用户导出 序列化器
@ -242,15 +267,15 @@ class UserViewSet(CustomModelViewSet):
search_fields = ["username", "name", "gender", "dept__name", "role__name"]
# 导出
export_field_label = {
"username":"用户账号",
"name":"用户名称",
"email":"用户邮箱",
"mobile":"手机号码",
"gender":"用户性别",
"is_active":"帐号状态",
"last_login":"最后登录时间",
"dept_name":"部门名称",
"dept_owner":"部门负责人",
"username": "用户账号",
"name": "用户名称",
"email": "用户邮箱",
"mobile": "手机号码",
"gender": "用户性别",
"is_active": "帐号状态",
"last_login": "最后登录时间",
"dept_name": "部门名称",
"dept_owner": "部门负责人",
}
export_serializer_class = ExportUserProfileSerializer
# 导入
@ -283,6 +308,7 @@ class UserViewSet(CustomModelViewSet):
user = request.user
result = {
"id": user.id,
"username": user.username,
"name": user.name,
"mobile": user.mobile,
"user_type": user.user_type,
@ -293,6 +319,9 @@ class UserViewSet(CustomModelViewSet):
"is_superuser": user.is_superuser,
"role": user.role.values_list('id', flat=True),
}
if hasattr(connection, 'tenant'):
result['tenant_id'] = connection.tenant and connection.tenant.id
result['tenant_name'] = connection.tenant and connection.tenant.name
dept = getattr(user, 'dept', None)
if dept:
result['dept_info'] = {
@ -307,8 +336,9 @@ class UserViewSet(CustomModelViewSet):
@action(methods=["PUT"], detail=False, permission_classes=[IsAuthenticated])
def update_user_info(self, request):
"""修改当前用户信息"""
user = request.user
Users.objects.filter(id=user.id).update(**request.data)
serializer = UserInfoUpdateSerializer(request.user, data=request.data, request=request)
serializer.is_valid(raise_exception=True)
serializer.save()
return DetailResponse(data=None, msg="修改成功")
@action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated])

BIN
web/public/image/avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 B

View File

@ -1,10 +1,12 @@
<template>
<el-color-picker
class="btn-text can-hover"
:value="value"
:predefine="predefine"
size="mini"
@change="set"/>
<el-tooltip effect="dark" :content="'颜色'" placement="bottom">
<el-color-picker
class="can-hover"
:value="value"
:predefine="predefine"
size="mini"
@change="set"/>
</el-tooltip>
</template>
<script>

View File

@ -8,7 +8,20 @@
-->
<template>
<el-dropdown size="small" class="d2-mr">
<span class="btn-text">{{
<el-link
type="primary"
:underline="false"
style="margin-bottom: 2px;margin-left: 10px"
v-if="isTenants"
>
<span>
当前租户{{info.tenant_name}}
</span>
<span class="btn-text">{{
info.name ? `你好 ${info.name}` : "未登录"
}}</span>
</el-link>
<span class="btn-text" v-else>{{
info.name ? `你好 ${info.name}` : "未登录"
}}</span>
<el-dropdown-menu slot="dropdown">
@ -20,7 +33,7 @@
注销
</el-dropdown-item>
</el-dropdown-menu>
<el-image v-if="info.avatar" :src="info.avatar" :preview-src-list="[info.avatar]" style="width: 20px;height: 20px" alt="头像"></el-image>
<el-image v-if="info.avatar" :src="info.avatar" :preview-src-list="[info.avatar]" style="width: 20px;height: 20px;border-radius: 20%;top: 5px;" alt="头像"></el-image>
</el-dropdown>
</template>
@ -30,6 +43,11 @@ export default {
computed: {
...mapState('d2admin/user', ['info'])
},
data () {
return {
isTenants: window.pluginsAll && window.pluginsAll.indexOf('dvadmin-tenants-web') !== -1
}
},
methods: {
...mapActions('d2admin/account', ['logout']),
/**

View File

@ -1,11 +1,3 @@
<!--
* @创建文件时间: 2021-07-26 23:08:16
* @Auther: 猿小天
* @最后修改人: 猿小天
* @最后修改时间: 2021-08-12 11:32:30
* 联系Qq:1638245306
* @文件介绍: 用户信息
-->
<template>
<d2-container class="page">
<el-tabs v-model="activeName" @tab-click="handleClick">
@ -14,42 +6,20 @@
<el-col :span="10" :offset="6">
<el-form
ref="userInfoForm"
label-width="100px"
:model="userInfo"
required-asterisk
:rules="userInforules"
:label-position="position"
center
>
<el-form-item prop="avatar" required label="头像">
<el-upload
class="avatar-uploader"
list-type="picture-card"
:file-list="fileList"
:action="action"
:headers="headers"
:limit="1"
:disabled="fileList.length === 1"
:on-success="handleAvatarSuccess"
>
<!-- <el-image
v-if="userInfo.avatar"
:src="userInfo.avatar"
:preview-src-list="[userInfo.avatar]"
style="width: 100px; height: 100px"
alt="头像"
></el-image>
<i
v-else
class="el-icon-plus avatar-uploader-icon"
style="width: 100px; height: 100px"
></i> -->
<i class="el-icon-plus"></i>
</el-upload>
<el-form-item prop="avatar" label="头像">
<d2p-cropper-uploader :value="userInfo.avatar || '/image/avatar.png'" @input="handleAvatarSuccess"/>
</el-form-item>
<el-form-item prop="name" required label="昵称">
<el-input v-model="userInfo.name" clearable></el-input>
</el-form-item>
<el-form-item label="电话号码" prop="mobile">
<el-form-item label="电话号码" required prop="mobile">
<el-input v-model="userInfo.mobile" clearable></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
@ -62,6 +32,22 @@
<el-radio :label="-1">未知</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="用户名" prop="dept">
<el-input :value="userInfo.username" clearable disabled></el-input>
</el-form-item>
<el-form-item label="所属部门" prop="dept">
<el-input :value="userInfo.dept_info && userInfo.dept_info.dept_name" clearable disabled></el-input>
</el-form-item>
<el-form-item label="当前角色" prop="role">
<el-select :value="userInfo.role" multiple placeholder="请选择" disabled style="width: 100%;">
<el-option
v-for="item in userInfo.role_info"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="updateInfo" type="primary">
<i class="fa fa-check"></i>
@ -83,6 +69,7 @@
ref="userPasswordForm"
:model="userPasswordInfo"
required-asterisk
label-width="100px"
:label-position="position"
:rules="passwordRules"
center
@ -90,6 +77,7 @@
<el-form-item label="原密码" required prop="oldPassword">
<el-input
v-model="userPasswordInfo.oldPassword"
placeholder="请输入原始密码"
clearable
></el-input>
</el-form-item>
@ -97,6 +85,7 @@
<el-input
type="password"
v-model="userPasswordInfo.newPassword"
placeholder="请输入新密码"
clearable
></el-input>
</el-form-item>
@ -104,6 +93,7 @@
<el-input
type="password"
v-model="userPasswordInfo.newPassword2"
placeholder="请再次输入新密码"
clearable
></el-input>
</el-form-item>
@ -206,7 +196,6 @@ export default {
params: {}
}).then((res) => {
_self.userInfo = res.data
_self.fileList = [{ name: 'avatar.png', url: res.data.avatar }]
})
},
/**
@ -217,10 +206,12 @@ export default {
_self.$refs.userInfoForm.validate((valid) => {
if (valid) {
const userInfo = _self.userInfo
delete userInfo.role
request({
url: '/api/system/user/update_user_info/',
method: 'put',
data: _self.userInfo
data: userInfo
}).then((res) => {
_self.$message.success('修改成功')
_self.getCurrentUserInfo()
@ -289,8 +280,7 @@ export default {
*/
handleAvatarSuccess (res, file) {
console.log(11, res)
this.fileList = [{ url: util.baseURL() + res.data.url, name: file.name }]
this.userInfo.avatar = util.baseURL() + res.data.url
this.userInfo.avatar = res
}
}
}

View File

@ -39,7 +39,7 @@ util.open = function (url) {
util.baseURL = function () {
var baseURL = process.env.VUE_APP_API
var param = baseURL.split('/')[3] || ''
if (window.pluginsAll && window.pluginsAll.indexOf('dvadmin-tenant-web') !== -1 && (!param || baseURL.startsWith('/'))) {
if (window.pluginsAll && window.pluginsAll.indexOf('dvadmin-tenants-web') !== -1 && (!param || baseURL.startsWith('/'))) {
// 1.把127.0.0.1 替换成和前端一样域名
// 2. ip 地址替换成和前端一样域名
// 3. /api 或其他类似的替换成和前端一样域名
@ -66,7 +66,7 @@ util.baseURL = function () {
util.wsBaseURL = function () {
var baseURL = process.env.VUE_APP_API
var param = baseURL.split('/')[3] || ''
if (window.pluginsAll && window.pluginsAll.indexOf('dvadmin-tenant-web') !== -1 && (!param || baseURL.startsWith('/'))) {
if (window.pluginsAll && window.pluginsAll.indexOf('dvadmin-tenants-web') !== -1 && (!param || baseURL.startsWith('/'))) {
// 1.把127.0.0.1 替换成和前端一样域名
// 2. ip 地址替换成和前端一样域名
// 3. /api 或其他类似的替换成和前端一样域名

View File

@ -62,14 +62,7 @@ router.beforeEach(async (to, from, next) => {
method: 'get',
params: {}
})
await store.dispatch('d2admin/user/set', {
name: res.data.name,
user_id: res.data.id,
avatar: res.data.avatar,
role_info: res.data.role_info,
dept_info: res.data.dept_info,
is_superuser: res.data.is_superuser
}, { root: true })
await store.dispatch('d2admin/user/set', res.data, { root: true })
await store.dispatch('d2admin/account/load')
store.dispatch('d2admin/dept/load')
store.dispatch('d2admin/settings/init')

View File

@ -11,6 +11,7 @@ import util from '@/libs/util.js'
import router from '@/router'
import store from '@/store/index'
import { SYS_USER_LOGIN, SYS_USER_LOGOUT } from '@/views/system/login/api'
import { request } from '@/api/service'
export default {
namespaced: true,
@ -44,13 +45,19 @@ export default {
util.cookies.set('token', res.access)
util.cookies.set('refresh', res.refresh)
// 设置 vuex 用户信息
await dispatch('d2admin/user/set', {
name: res.name,
user_id: res.userId,
avatar: res.avatar,
role_info: res.role_info,
dept_info: res.dept_info
}, { root: true })
// await dispatch('d2admin/user/set', {
// name: res.name,
// user_id: res.userId,
// avatar: res.avatar,
// role_info: res.role_info,
// dept_info: res.dept_info
// }, { root: true })
var userInfoRes = await request({
url: '/api/system/user/user_info/',
method: 'get',
params: {}
})
await store.dispatch('d2admin/user/set', userInfoRes.data, { root: true })
// 用户登录后从持久化数据加载一系列的设置
await dispatch('load')
},