From 0ccf2e3725cf8f66309055627cf74895592b246d Mon Sep 17 00:00:00 2001
From: H0nGzA1 <2505811377@qq.com>
Date: Tue, 11 Apr 2023 18:40:20 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20=F0=9F=90=9B=20=E5=A4=B4=E5=83=8F?=
=?UTF-8?q?=E4=B8=8A=E4=BC=A0=EF=BC=8C=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?=
=?UTF-8?q?=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
backend/dvadmin/system/views/file_list.py | 9 +
backend/dvadmin/system/views/menu.py | 1 -
.../dvadmin/system/views/message_center.py | 26 +--
web/package.json | 1 +
web/src/components/avatarSelector/index.vue | 171 ++++++++++++++++++
web/src/stores/interface/index.ts | 14 +-
web/src/stores/userInfo.ts | 36 +++-
web/src/utils/tools.ts | 81 ++++++---
.../views/system/login/component/account.vue | 4 +-
web/src/views/system/personal/api.ts | 61 ++++---
web/src/views/system/personal/index.vue | 25 ++-
web/yarn.lock | 5 +
12 files changed, 348 insertions(+), 86 deletions(-)
create mode 100644 web/src/components/avatarSelector/index.vue
diff --git a/backend/dvadmin/system/views/file_list.py b/backend/dvadmin/system/views/file_list.py
index 82fc757..ae05084 100644
--- a/backend/dvadmin/system/views/file_list.py
+++ b/backend/dvadmin/system/views/file_list.py
@@ -1,6 +1,9 @@
from rest_framework import serializers
+from rest_framework.decorators import action
+from rest_framework.parsers import FileUploadParser
from dvadmin.system.models import FileList
+from dvadmin.utils.json_response import SuccessResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
@@ -16,6 +19,7 @@ class FileSerializer(CustomModelSerializer):
fields = "__all__"
def create(self, validated_data):
+ print(self.context['request'])
validated_data['name'] = str(self.initial_data.get('file'))
validated_data['url'] = self.initial_data.get('file')
return super().create(validated_data)
@@ -34,3 +38,8 @@ class FileViewSet(CustomModelViewSet):
serializer_class = FileSerializer
filter_fields = ['name', ]
permission_classes = []
+
+ @action(detail=False, methods=['post'])
+ def test_post_file(self, request):
+
+ return SuccessResponse(msg='test_is_ok')
diff --git a/backend/dvadmin/system/views/menu.py b/backend/dvadmin/system/views/menu.py
index 527ee7e..028ed40 100644
--- a/backend/dvadmin/system/views/menu.py
+++ b/backend/dvadmin/system/views/menu.py
@@ -117,7 +117,6 @@ class MenuViewSet(CustomModelViewSet):
"""前端拖拽菜单之后重写parent"""
menu_id = request.data['menu_id']
parent_id = request.data['parent_id']
- print(parent_id)
menu = Menu.objects.get(id=menu_id)
menu.parent_id = parent_id
menu.save()
diff --git a/backend/dvadmin/system/views/message_center.py b/backend/dvadmin/system/views/message_center.py
index ad3c680..96b23c3 100644
--- a/backend/dvadmin/system/views/message_center.py
+++ b/backend/dvadmin/system/views/message_center.py
@@ -85,7 +85,7 @@ class MessageCenterTargetUserListSerializer(CustomModelSerializer):
def get_is_read(self, instance):
user_id = self.request.user.id
message_center_id = instance.id
- queryset = MessageCenterTargetUser.objects.filter(messagecenter__id=message_center_id,users_id=user_id).first()
+ queryset = MessageCenterTargetUser.objects.filter(messagecenter__id=message_center_id, users_id=user_id).first()
if queryset:
return queryset.is_read
return False
@@ -95,21 +95,22 @@ class MessageCenterTargetUserListSerializer(CustomModelSerializer):
fields = "__all__"
read_only_fields = ["id"]
+
def websocket_push(user_id, message):
"""
主动推送消息
"""
- username = "user_"+str(user_id)
- print(103,message)
+ username = "user_" + str(user_id)
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
- username,
- {
- "type": "push.message",
- "json": message
- }
+ username,
+ {
+ "type": "push.message",
+ "json": message
+ }
)
+
class MessageCenterCreateSerializer(CustomModelSerializer):
"""
消息中心-新增-序列化器
@@ -122,10 +123,10 @@ class MessageCenterCreateSerializer(CustomModelSerializer):
# 在保存之前,根据目标类型,把目标用户查询出来并保存
users = initial_data.get('target_user', [])
if target_type in [1]: # 按角色
- target_role = initial_data.get('target_role',[])
+ target_role = initial_data.get('target_role', [])
users = Users.objects.filter(role__id__in=target_role).values_list('id', flat=True)
if target_type in [2]: # 按部门
- target_dept = initial_data.get('target_dept',[])
+ target_dept = initial_data.get('target_dept', [])
users = Users.objects.filter(dept__id__in=target_dept).values_list('id', flat=True)
if target_type in [3]: # 系统通知
users = Users.objects.values_list('id', flat=True)
@@ -141,7 +142,7 @@ class MessageCenterCreateSerializer(CustomModelSerializer):
for user in users:
unread_count = MessageCenterTargetUser.objects.filter(users__id=user, is_read=False).count()
websocket_push(user, message={"sender": 'system', "contentType": 'SYSTEM',
- "content": '您有一条新消息~', "unread": unread_count})
+ "content": '您有一条新消息~', "unread": unread_count})
return data
class Meta:
@@ -184,7 +185,7 @@ class MessageCenterViewSet(CustomModelViewSet):
# 主动推送消息
unread_count = MessageCenterTargetUser.objects.filter(users__id=user_id, is_read=False).count()
websocket_push(user_id, message={"sender": 'system', "contentType": 'TEXT',
- "content": '您查看了一条消息~', "unread": unread_count})
+ "content": '您查看了一条消息~', "unread": unread_count})
return DetailResponse(data=serializer.data, msg="获取成功")
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
@@ -195,7 +196,6 @@ class MessageCenterViewSet(CustomModelViewSet):
self_user_id = self.request.user.id
# queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).order_by('-create_datetime')
queryset = MessageCenter.objects.filter(target_user__id=self_user_id)
- print(queryset)
# queryset = self.filter_queryset(queryset)
page = self.paginate_queryset(queryset)
if page is not None:
diff --git a/web/package.json b/web/package.json
index 93136e9..4349cde 100644
--- a/web/package.json
+++ b/web/package.json
@@ -45,6 +45,7 @@
"ts-md5": "^1.3.1",
"vue": "^3.2.45",
"vue-clipboard3": "^2.0.0",
+ "vue-cropper": "^1.0.8",
"vue-grid-layout": "^3.0.0-beta1",
"vue-i18n": "^9.2.2",
"vue-router": "^4.1.6",
diff --git a/web/src/components/avatarSelector/index.vue b/web/src/components/avatarSelector/index.vue
new file mode 100644
index 0000000..cafd4d9
--- /dev/null
+++ b/web/src/components/avatarSelector/index.vue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 选择
+
+
+
+
+
+
+
+
+
+
+
+ 更新头像
+
+
+
+
+
+
+
+
+
diff --git a/web/src/stores/interface/index.ts b/web/src/stores/interface/index.ts
index 794b603..e60a85f 100644
--- a/web/src/stores/interface/index.ts
+++ b/web/src/stores/interface/index.ts
@@ -5,11 +5,17 @@
// 用户信息
export interface UserInfosState {
- authBtnList: string[];
- photo: string;
- roles: string[];
- time: number;
+ avatar: string;
userName: string;
+ name: string;
+ email: string;
+ mobile: string;
+ gender: string;
+ dept_info: {
+ dept_id: number;
+ dept_name: string;
+ };
+ role_info: any[];
}
export interface UserInfosStates {
userInfos: UserInfosState;
diff --git a/web/src/stores/userInfo.ts b/web/src/stores/userInfo.ts
index 88ab8a5..1bfd307 100644
--- a/web/src/stores/userInfo.ts
+++ b/web/src/stores/userInfo.ts
@@ -11,11 +11,22 @@ import { request } from '../utils/service';
export const useUserInfo = defineStore('userInfo', {
state: (): UserInfosStates => ({
userInfos: {
+ avatar: '',
userName: '',
- photo: '',
- time: 0,
- roles: [],
- authBtnList: [],
+ name: '',
+ email: '',
+ mobile: '',
+ gender: '',
+ dept_info: {
+ dept_id: 0,
+ dept_name: '',
+ },
+ role_info: [
+ {
+ id: 0,
+ name: '',
+ },
+ ],
},
}),
actions: {
@@ -26,17 +37,22 @@ export const useUserInfo = defineStore('userInfo', {
} else {
let userInfos: any = await this.getApiUserInfo();
this.userInfos.userName = userInfos.data.name;
- this.userInfos.photo = userInfos.data.avatar || 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500'
- this.userInfos.time = new Date().getTime()
- this.userInfos.roles = ['admin']
- Session.set('userInfo', this.userInfos)
+ this.userInfos.avatar =
+ userInfos.data.avatar || 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500';
+ this.userInfos.name = userInfos.data.name;
+ this.userInfos.email = userInfos.data.email;
+ this.userInfos.mobile = userInfos.data.mobile;
+ this.userInfos.gender = userInfos.data.gender;
+ this.userInfos.dept_info = userInfos.data.dept_info;
+ this.userInfos.role_info = userInfos.data.role_info;
+ Session.set('userInfo', this.userInfos);
}
},
async getApiUserInfo() {
return request({
url: '/api/system/user/user_info/',
method: 'get',
- })
- }
+ });
+ },
},
});
diff --git a/web/src/utils/tools.ts b/web/src/utils/tools.ts
index 439b927..15645ae 100644
--- a/web/src/utils/tools.ts
+++ b/web/src/utils/tools.ts
@@ -3,16 +3,16 @@
* @param {String} jsonString 需要解析的 json 字符串
* @param {String} defaultValue 默认值
*/
-import { uiContext } from "@fast-crud/fast-crud";
+import { uiContext } from '@fast-crud/fast-crud';
-export function parse(jsonString = "{}", defaultValue = {}) {
- let result = defaultValue;
- try {
- result = JSON.parse(jsonString);
- } catch (error) {
- console.log(error);
- }
- return result;
+export function parse(jsonString = '{}', defaultValue = {}) {
+ let result = defaultValue;
+ try {
+ result = JSON.parse(jsonString);
+ } catch (error) {
+ console.log(error);
+ }
+ return result;
}
/**
@@ -21,8 +21,8 @@ export function parse(jsonString = "{}", defaultValue = {}) {
* @param {String} msg 状态信息
* @param {Number} code 状态码
*/
-export function response(data = {}, msg = "", code = 0) {
- return [200, { code, msg, data }];
+export function response(data = {}, msg = '', code = 0) {
+ return [200, { code, msg, data }];
}
/**
@@ -30,8 +30,8 @@ export function response(data = {}, msg = "", code = 0) {
* @param {Any} data 返回值
* @param {String} msg 状态信息
*/
-export function responseSuccess(data = {}, msg = "成功") {
- return response(data, msg);
+export function responseSuccess(data = {}, msg = '成功') {
+ return response(data, msg);
}
/**
@@ -40,30 +40,57 @@ export function responseSuccess(data = {}, msg = "成功") {
* @param {String} msg 状态信息
* @param {Number} code 状态码
*/
-export function responseError(data = {}, msg = "请求失败", code = 500) {
- return response(data, msg, code);
+export function responseError(data = {}, msg = '请求失败', code = 500) {
+ return response(data, msg, code);
}
/**
* @description 记录和显示错误
* @param {Error} error 错误对象
*/
-export function errorLog(error:any,notification=true) {
- // 打印到控制台
- console.error(error);
- // 显示提示
- if(notification){
- uiContext.get().notification.error({ message: error.message });
- }
-
+export function errorLog(error: any, notification = true) {
+ // 打印到控制台
+ console.error(error);
+ // 显示提示
+ if (notification) {
+ uiContext.get().notification.error({ message: error.message });
+ }
}
/**
* @description 创建一个错误
* @param {String} msg 错误信息
*/
-export function errorCreate(msg:any,notification=true) {
- const error = new Error(msg);
- errorLog(error,notification);
- // throw error;
+export function errorCreate(msg: any, notification = true) {
+ const error = new Error(msg);
+ errorLog(error, notification);
+ // throw error;
+}
+
+export function base64ToFile(base64: any, fileName: string) {
+ // 将base64按照 , 进行分割 将前缀 与后续内容分隔开
+ let data = base64.split(',');
+ // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等)
+ let type = data[0].match(/:(.*?);/)[1];
+ // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp)
+ let suffix = type.split('/')[1];
+ // 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出
+ const bstr = window.atob(data[1]);
+ // 获取解码结果字符串的长度
+ let n = bstr.length;
+ // 根据解码结果字符串的长度创建一个等长的整形数字数组
+ // 但在创建时 所有元素初始值都为 0
+ const u8arr = new Uint8Array(n);
+ // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
+ while (n--) {
+ // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元
+ u8arr[n] = bstr.charCodeAt(n);
+ }
+ // 利用构造函数创建File文件对象
+ // new File(bits, name, options)
+ const file = new File([u8arr], `${fileName}.${suffix}`, {
+ type: type,
+ });
+ // 将File文件对象返回给方法的调用者
+ return file;
}
diff --git a/web/src/views/system/login/component/account.vue b/web/src/views/system/login/component/account.vue
index 6b92ffb..585cf4c 100644
--- a/web/src/views/system/login/component/account.vue
+++ b/web/src/views/system/login/component/account.vue
@@ -89,8 +89,8 @@ export default defineComponent({
const state = reactive({
isShowPassword: false,
ruleForm: {
- username: 'superadmin',
- password: 'admin123456',
+ username: '',
+ password: '',
captcha: '',
captchaKey: '',
captchaImgBase: '',
diff --git a/web/src/views/system/personal/api.ts b/web/src/views/system/personal/api.ts
index c68e5f2..f5243d8 100644
--- a/web/src/views/system/personal/api.ts
+++ b/web/src/views/system/personal/api.ts
@@ -1,40 +1,38 @@
import { request } from '/@/utils/service';
import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
-import {apiPrefix} from "/@/views/system/messageCenter/api";
+import { apiPrefix } from '/@/views/system/messageCenter/api';
export function GetUserInfo(query: PageQuery) {
- return request({
- url: '/api/system/user/user_info/',
- method: 'get',
- params: query
- });
+ return request({
+ url: '/api/system/user/user_info/',
+ method: 'get',
+ params: query,
+ });
}
-
/**
* 更新用户信息
* @param data
*/
export function updateUserInfo(data: AddReq) {
- return request({
- url: '/api/system/user/update_user_info/',
- method: 'put',
- data: data
- })
+ return request({
+ url: '/api/system/user/update_user_info/',
+ method: 'put',
+ data: data,
+ });
}
-
/**
* 获取自己接收的消息
* @param query
* @returns {*}
* @constructor
*/
-export function GetSelfReceive (query:PageQuery) {
- return request({
- url: '/api/system/message_center/get_self_receive/',
- method: 'get',
- params: query
- })
+export function GetSelfReceive(query: PageQuery) {
+ return request({
+ url: '/api/system/message_center/get_self_receive/',
+ method: 'get',
+ params: query,
+ });
}
/***
@@ -42,9 +40,24 @@ export function GetSelfReceive (query:PageQuery) {
* @param data
*/
export function UpdatePassword(data: EditReq) {
- return request({
- url: '/api/system/user/change_password/',
- method: 'put',
- data: data
- })
+ return request({
+ url: '/api/system/user/change_password/',
+ method: 'put',
+ data: data,
+ });
+}
+
+/***
+ * 上传头像
+ * @param data
+ */
+export function uploadAvatar(data: AddReq) {
+ return request({
+ url: 'api/system/file/',
+ method: 'post',
+ data: data,
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ });
}
diff --git a/web/src/views/system/personal/index.vue b/web/src/views/system/personal/index.vue
index 14f53e5..d6d295e 100644
--- a/web/src/views/system/personal/index.vue
+++ b/web/src/views/system/personal/index.vue
@@ -6,10 +6,9 @@
-
-
-
-
+
+
+
@@ -174,13 +173,18 @@