功能变化: 优化用户信息

pull/81/head
李强 2022-11-26 20:49:30 +08:00
parent f419f277b2
commit 5cb4e85f48
8 changed files with 112 additions and 80 deletions

View File

@ -5,7 +5,7 @@ from django_restql.fields import DynamicSerializerMethodField
from rest_framework import serializers from rest_framework import serializers
from rest_framework.decorators import action, permission_classes from rest_framework.decorators import action, permission_classes
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from django.db import connection
from application import dispatch from application import dispatch
from dvadmin.system.models import Users, Role, Dept from dvadmin.system.models import Users, Role, Dept
from dvadmin.system.views.role import RoleSerializer from dvadmin.system.views.role import RoleSerializer
@ -15,17 +15,18 @@ from dvadmin.utils.validator import CustomUniqueValidator
from dvadmin.utils.viewset import CustomModelViewSet from dvadmin.utils.viewset import CustomModelViewSet
def recursion(instance,parent,result): def recursion(instance, parent, result):
new_instance = getattr(instance,parent,None) new_instance = getattr(instance, parent, None)
res = [] res = []
data = getattr(instance, result, None) data = getattr(instance, result, None)
if data: if data:
res.append(data) res.append(data)
if new_instance: if new_instance:
array = recursion(new_instance,parent,result) array = recursion(new_instance, parent, result)
res+=(array) res += (array)
return res return res
class UserSerializer(CustomModelSerializer): class UserSerializer(CustomModelSerializer):
""" """
用户管理-序列化器 用户管理-序列化器
@ -63,12 +64,13 @@ class UsersInitSerializer(CustomModelSerializer):
""" """
初始化获取数信息(用于生成初始化json文件) 初始化获取数信息(用于生成初始化json文件)
""" """
def save(self, **kwargs): def save(self, **kwargs):
instance = super().save(**kwargs) instance = super().save(**kwargs)
role_key = self.initial_data.get('role_key',[]) role_key = self.initial_data.get('role_key', [])
role_ids = Role.objects.filter(key__in=role_key).values_list('id',flat=True) role_ids = Role.objects.filter(key__in=role_key).values_list('id', flat=True)
instance.role.set(role_ids) 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() dept_id = Dept.objects.filter(key=dept_key).first()
instance.dept = dept_id instance.dept = dept_id
instance.save() 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): class ExportUserProfileSerializer(CustomModelSerializer):
""" """
用户导出 序列化器 用户导出 序列化器
@ -242,15 +267,15 @@ class UserViewSet(CustomModelViewSet):
search_fields = ["username", "name", "gender", "dept__name", "role__name"] search_fields = ["username", "name", "gender", "dept__name", "role__name"]
# 导出 # 导出
export_field_label = { export_field_label = {
"username":"用户账号", "username": "用户账号",
"name":"用户名称", "name": "用户名称",
"email":"用户邮箱", "email": "用户邮箱",
"mobile":"手机号码", "mobile": "手机号码",
"gender":"用户性别", "gender": "用户性别",
"is_active":"帐号状态", "is_active": "帐号状态",
"last_login":"最后登录时间", "last_login": "最后登录时间",
"dept_name":"部门名称", "dept_name": "部门名称",
"dept_owner":"部门负责人", "dept_owner": "部门负责人",
} }
export_serializer_class = ExportUserProfileSerializer export_serializer_class = ExportUserProfileSerializer
# 导入 # 导入
@ -293,6 +318,9 @@ class UserViewSet(CustomModelViewSet):
"is_superuser": user.is_superuser, "is_superuser": user.is_superuser,
"role": user.role.values_list('id', flat=True), "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) dept = getattr(user, 'dept', None)
if dept: if dept:
result['dept_info'] = { result['dept_info'] = {
@ -307,8 +335,9 @@ class UserViewSet(CustomModelViewSet):
@action(methods=["PUT"], detail=False, permission_classes=[IsAuthenticated]) @action(methods=["PUT"], detail=False, permission_classes=[IsAuthenticated])
def update_user_info(self, request): def update_user_info(self, request):
"""修改当前用户信息""" """修改当前用户信息"""
user = request.user serializer = UserInfoUpdateSerializer(request.user, data=request.data, request=request)
Users.objects.filter(id=user.id).update(**request.data) serializer.is_valid(raise_exception=True)
serializer.save()
return DetailResponse(data=None, msg="修改成功") return DetailResponse(data=None, msg="修改成功")
@action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated]) @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> <template>
<el-color-picker <el-tooltip effect="dark" :content="'颜色'" placement="bottom">
class="btn-text can-hover" <el-color-picker
:value="value" class="can-hover"
:predefine="predefine" :value="value"
size="mini" :predefine="predefine"
@change="set"/> size="mini"
@change="set"/>
</el-tooltip>
</template> </template>
<script> <script>

View File

@ -8,7 +8,20 @@
--> -->
<template> <template>
<el-dropdown size="small" class="d2-mr"> <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}` : "未登录" info.name ? `你好 ${info.name}` : "未登录"
}}</span> }}</span>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
@ -30,6 +43,11 @@ export default {
computed: { computed: {
...mapState('d2admin/user', ['info']) ...mapState('d2admin/user', ['info'])
}, },
data () {
return {
isTenants: window.pluginsAll && window.pluginsAll.indexOf('dvadmin-tenants-web') !== -1
}
},
methods: { methods: {
...mapActions('d2admin/account', ['logout']), ...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> <template>
<d2-container class="page"> <d2-container class="page">
<el-tabs v-model="activeName" @tab-click="handleClick"> <el-tabs v-model="activeName" @tab-click="handleClick">
@ -14,37 +6,15 @@
<el-col :span="10" :offset="6"> <el-col :span="10" :offset="6">
<el-form <el-form
ref="userInfoForm" ref="userInfoForm"
label-width="100px"
:model="userInfo" :model="userInfo"
required-asterisk required-asterisk
:rules="userInforules" :rules="userInforules"
:label-position="position" :label-position="position"
center center
> >
<el-form-item prop="avatar" required label="头像"> <el-form-item prop="avatar" label="头像">
<el-upload <d2p-cropper-uploader :value="userInfo.avatar || '/image/avatar.png'" @input="handleAvatarSuccess"/>
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> </el-form-item>
<el-form-item prop="name" required label="昵称"> <el-form-item prop="name" required label="昵称">
<el-input v-model="userInfo.name" clearable></el-input> <el-input v-model="userInfo.name" clearable></el-input>
@ -52,6 +22,19 @@
<el-form-item label="电话号码" prop="mobile"> <el-form-item label="电话号码" prop="mobile">
<el-input v-model="userInfo.mobile" clearable></el-input> <el-input v-model="userInfo.mobile" clearable></el-input>
</el-form-item> </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="请选择" size="mini" disabled>
<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 label="邮箱" prop="email"> <el-form-item label="邮箱" prop="email">
<el-input v-model="userInfo.email" clearable></el-input> <el-input v-model="userInfo.email" clearable></el-input>
</el-form-item> </el-form-item>
@ -206,7 +189,6 @@ export default {
params: {} params: {}
}).then((res) => { }).then((res) => {
_self.userInfo = res.data _self.userInfo = res.data
_self.fileList = [{ name: 'avatar.png', url: res.data.avatar }]
}) })
}, },
/** /**
@ -217,10 +199,12 @@ export default {
_self.$refs.userInfoForm.validate((valid) => { _self.$refs.userInfoForm.validate((valid) => {
if (valid) { if (valid) {
const userInfo = _self.userInfo
delete userInfo.role
request({ request({
url: '/api/system/user/update_user_info/', url: '/api/system/user/update_user_info/',
method: 'put', method: 'put',
data: _self.userInfo data: userInfo
}).then((res) => { }).then((res) => {
_self.$message.success('修改成功') _self.$message.success('修改成功')
_self.getCurrentUserInfo() _self.getCurrentUserInfo()
@ -289,8 +273,7 @@ export default {
*/ */
handleAvatarSuccess (res, file) { handleAvatarSuccess (res, file) {
console.log(11, res) console.log(11, res)
this.fileList = [{ url: util.baseURL() + res.data.url, name: file.name }] this.userInfo.avatar = res
this.userInfo.avatar = util.baseURL() + res.data.url
} }
} }
} }

View File

@ -39,7 +39,7 @@ util.open = function (url) {
util.baseURL = function () { util.baseURL = function () {
var baseURL = process.env.VUE_APP_API var baseURL = process.env.VUE_APP_API
var param = baseURL.split('/')[3] || '' 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 替换成和前端一样域名 // 1.把127.0.0.1 替换成和前端一样域名
// 2. ip 地址替换成和前端一样域名 // 2. ip 地址替换成和前端一样域名
// 3. /api 或其他类似的替换成和前端一样域名 // 3. /api 或其他类似的替换成和前端一样域名
@ -66,7 +66,7 @@ util.baseURL = function () {
util.wsBaseURL = function () { util.wsBaseURL = function () {
var baseURL = process.env.VUE_APP_API var baseURL = process.env.VUE_APP_API
var param = baseURL.split('/')[3] || '' 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 替换成和前端一样域名 // 1.把127.0.0.1 替换成和前端一样域名
// 2. ip 地址替换成和前端一样域名 // 2. ip 地址替换成和前端一样域名
// 3. /api 或其他类似的替换成和前端一样域名 // 3. /api 或其他类似的替换成和前端一样域名

View File

@ -62,14 +62,7 @@ router.beforeEach(async (to, from, next) => {
method: 'get', method: 'get',
params: {} params: {}
}) })
await store.dispatch('d2admin/user/set', { await store.dispatch('d2admin/user/set', res.data, { root: true })
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/account/load') await store.dispatch('d2admin/account/load')
store.dispatch('d2admin/dept/load') store.dispatch('d2admin/dept/load')
store.dispatch('d2admin/settings/init') store.dispatch('d2admin/settings/init')

View File

@ -11,6 +11,7 @@ import util from '@/libs/util.js'
import router from '@/router' import router from '@/router'
import store from '@/store/index' import store from '@/store/index'
import { SYS_USER_LOGIN, SYS_USER_LOGOUT } from '@/views/system/login/api' import { SYS_USER_LOGIN, SYS_USER_LOGOUT } from '@/views/system/login/api'
import { request } from '@/api/service'
export default { export default {
namespaced: true, namespaced: true,
@ -44,13 +45,19 @@ export default {
util.cookies.set('token', res.access) util.cookies.set('token', res.access)
util.cookies.set('refresh', res.refresh) util.cookies.set('refresh', res.refresh)
// 设置 vuex 用户信息 // 设置 vuex 用户信息
await dispatch('d2admin/user/set', { // await dispatch('d2admin/user/set', {
name: res.name, // name: res.name,
user_id: res.userId, // user_id: res.userId,
avatar: res.avatar, // avatar: res.avatar,
role_info: res.role_info, // role_info: res.role_info,
dept_info: res.dept_info // dept_info: res.dept_info
}, { root: true }) // }, { 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') await dispatch('load')
}, },