From f2f01f7043fc68ee986f3ae72e13f84c2cb39641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Wed, 16 Nov 2022 22:09:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8F=98=E5=8C=96:=20?= =?UTF-8?q?=E5=AE=8C=E6=88=90websocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/application/websocketConfig.py | 25 +++++--- .../dvadmin/system/views/message_center.py | 60 ++++++++++++------- web/package.json | 2 +- web/src/api/websocket.js | 19 ++++-- .../components/header-message/index.vue | 27 +++++++-- .../modules/d2admin/modules/messagecenter.js | 35 +++++++++++ 6 files changed, 127 insertions(+), 41 deletions(-) create mode 100644 web/src/store/modules/d2admin/modules/messagecenter.js diff --git a/backend/application/websocketConfig.py b/backend/application/websocketConfig.py index 1c811b2..a4be5c5 100644 --- a/backend/application/websocketConfig.py +++ b/backend/application/websocketConfig.py @@ -10,12 +10,12 @@ from channels.layers import get_channel_layer from jwt import InvalidSignatureError from application import settings -from dvadmin.system.models import MessageCenter +from dvadmin.system.models import MessageCenter, MessageCenterTargetUser send_dict = {} # 发送消息结构体 -def message(sender, msg_type, msg): +def set_message(sender, msg_type, msg): text = { 'sender': sender, 'contentType': msg_type, @@ -32,6 +32,11 @@ def _get_message_center_instance(message_id): else: return [] +@database_sync_to_async +def _get_message_unread(user_id): + count = MessageCenterTargetUser.objects.filter(users=user_id,is_read=False).count() + return count or 0 + def request_data(scope): query_string = scope.get('query_string', b'').decode('utf-8') @@ -53,7 +58,11 @@ class DvadminWebSocket(AsyncJsonWebsocketConsumer): self.channel_name ) await self.accept() - await self.send_json(message('system', 'SYSTEM', '连接成功')) + # 发送连接成功 + await self.send_json(set_message('system', 'SYSTEM', '连接成功')) + # 主动推送消息 + unread_count = await _get_message_unread(self.user_id) + await self.send_json(set_message('system', 'TEXT', {"model":'message_center',"unread":unread_count})) except InvalidSignatureError: await self.disconnect(None) @@ -78,23 +87,25 @@ class MegCenter(DvadminWebSocket): for send_user in user_list: await self.channel_layer.group_send( "user_" + str(send_user), - {'type': 'push.message', 'message': text_data_json} + {'type': 'push.message', 'json': text_data_json} ) async def push_message(self, event): - message = event['message'] + message = event['json'] await self.send(text_data=json.dumps(message)) -def push(username, event): +def websocket_push(user_id, message): """ 主动推送消息 """ + username = "user_"+str(user_id) + print(103,message) channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)( username, { "type": "push.message", - "event": event + "json": message } ) \ No newline at end of file diff --git a/backend/dvadmin/system/views/message_center.py b/backend/dvadmin/system/views/message_center.py index bbda1f9..7475814 100644 --- a/backend/dvadmin/system/views/message_center.py +++ b/backend/dvadmin/system/views/message_center.py @@ -5,6 +5,7 @@ from rest_framework import serializers from rest_framework.decorators import action, permission_classes from rest_framework.permissions import IsAuthenticated, AllowAny +from application.websocketConfig import websocket_push from dvadmin.system.models import MessageCenter, Users, MessageCenterTargetUser from dvadmin.system.views.dept import DeptSerializer from dvadmin.system.views.role import RoleSerializer @@ -21,9 +22,10 @@ class MessageCenterSerializer(CustomModelSerializer): role_info = DynamicSerializerMethodField() user_info = DynamicSerializerMethodField() dept_info = DynamicSerializerMethodField() - is_read = serializers.BooleanField(read_only=True,source='target_user__is_read') + is_read = serializers.BooleanField(read_only=True, source='target_user__is_read') + def get_role_info(self, instance, parsed_query): - roles =instance.target_role.all() + roles = instance.target_role.all() # You can do what ever you want in here # `parsed_query` param is passed to BookSerializer to allow further querying serializer = RoleSerializer( @@ -54,6 +56,7 @@ class MessageCenterSerializer(CustomModelSerializer): parsed_query=parsed_query ) return serializer.data + class Meta: model = MessageCenter fields = "__all__" @@ -64,15 +67,18 @@ class MessageCenterTargetUserSerializer(CustomModelSerializer): """ 目标用户序列化器-序列化器 """ + class Meta: model = MessageCenterTargetUser fields = "__all__" read_only_fields = ["id"] + class MessageCenterTargetUserListSerializer(CustomModelSerializer): """ 目标用户序列化器-序列化器 """ + class Meta: model = MessageCenterTargetUser fields = "__all__" @@ -97,22 +103,28 @@ class MessageCenterCreateSerializer(CustomModelSerializer): initial_data = self.initial_data target_type = initial_data.get('target_type') # 在保存之前,根据目标类型,把目标用户查询出来并保存 - users = initial_data.get('target_user',[]) - if target_type in [1]: #按角色 + users = initial_data.get('target_user', []) + if target_type in [1]: # 按角色 target_role = initial_data.get('target_role') - users = Users.objects.exclude(is_deleted=True).filter(role__id__in=target_role).values_list('id',flat=True) - if target_type in [2]: #按部门 + users = Users.objects.exclude(is_deleted=True).filter(role__id__in=target_role).values_list('id', flat=True) + if target_type in [2]: # 按部门 target_dept = initial_data.get('target_dept') - users = Users.objects.exclude(is_deleted=True).filter(dept__id__in=target_dept).values_list('id',flat=True) - if target_type in [3]: #系统通知 - users = Users.objects.exclude(is_deleted=True).values_list('id',flat=True) - targetuser_data = [{ - "messagecenter": data.id, - "users": user - } for user in users] + users = Users.objects.exclude(is_deleted=True).filter(dept__id__in=target_dept).values_list('id', flat=True) + if target_type in [3]: # 系统通知 + users = Users.objects.exclude(is_deleted=True).values_list('id', flat=True) + targetuser_data = [] + for user in users: + targetuser_data.append({ + "messagecenter": data.id, + "users": user + }) targetuser_instance = MessageCenterTargetUserSerializer(data=targetuser_data, many=True, request=self.request) targetuser_instance.is_valid(raise_exception=True) targetuser_instance.save() + for user in users: + unread_count = MessageCenterTargetUser.objects.filter(users__id=user, is_read=False).count() + websocket_push(user, {"sender": 'system', "contentType": 'TEXT', + "content": {"model": 'message_center', "unread": unread_count}}) return data class Meta: @@ -121,8 +133,6 @@ class MessageCenterCreateSerializer(CustomModelSerializer): read_only_fields = ["id"] - - class MessageCenterViewSet(CustomModelViewSet): """ 消息中心接口 @@ -138,7 +148,7 @@ class MessageCenterViewSet(CustomModelViewSet): extra_filter_backends = [] def get_queryset(self): - if self.action=='list': + if self.action == 'list': return MessageCenter.objects.filter(creator=self.request.user.id).all() return MessageCenter.objects.all() @@ -148,22 +158,26 @@ class MessageCenterViewSet(CustomModelViewSet): """ pk = kwargs.get('pk') user_id = self.request.user.id - queryset = MessageCenterTargetUser.objects.filter(users__id=user_id,messagecenter__id=pk).first() + queryset = MessageCenterTargetUser.objects.filter(users__id=user_id, messagecenter__id=pk).first() if queryset: queryset.is_read = True queryset.save() instance = self.get_object() serializer = self.get_serializer(instance) + # 主动推送消息 + unread_count = MessageCenterTargetUser.objects.filter(users__id=user_id, is_read=False).count() + websocket_push(user_id, {"sender": 'system', "contentType": 'TEXT', + "content": {"model": 'message_center', "unread": unread_count}}) return DetailResponse(data=serializer.data, msg="获取成功") - - @action(methods=['GET'],detail=False,permission_classes=[IsAuthenticated]) - def get_self_receive(self,request): + @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated]) + def get_self_receive(self, request): """ 获取接收到的消息 """ self_user_id = self.request.user.id - queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).exclude(messagecenter__is_deleted=True).order_by('-create_datetime') + queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).exclude( + messagecenter__is_deleted=True).order_by('-create_datetime') # queryset = self.filter_queryset(queryset) page = self.paginate_queryset(queryset) if page is not None: @@ -173,7 +187,7 @@ class MessageCenterViewSet(CustomModelViewSet): return SuccessResponse(data=serializer.data, msg="获取成功") @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated]) - def get_newest_msg(self,request): + def get_newest_msg(self, request): """ 获取最新的一条消息 """ @@ -184,4 +198,4 @@ class MessageCenterViewSet(CustomModelViewSet): if queryset: serializer = MessageCenterTargetUserListSerializer(queryset, many=False, request=request) data = serializer.data - return DetailResponse(data=data, msg="获取成功") \ No newline at end of file + return DetailResponse(data=data, msg="获取成功") diff --git a/web/package.json b/web/package.json index 1aa01a4..32044c8 100644 --- a/web/package.json +++ b/web/package.json @@ -44,7 +44,7 @@ "vue": "^2.6.11", "vue-i18n": "^8.15.1", "vue-infinite-scroll": "^2.0.2", - "vue-router": "^3.1.3", + "vue-router": "^3.6.5", "vue-splitpane": "^1.0.6", "vuex": "^3.1.2", "vxe-table": "^3.3.2", diff --git a/web/src/api/websocket.js b/web/src/api/websocket.js index d38ad05..e9b24e1 100644 --- a/web/src/api/websocket.js +++ b/web/src/api/websocket.js @@ -1,5 +1,6 @@ import ElementUI from 'element-ui' import util from '@/libs/util' +import store from '@/store' function initWebSocket (e) { const token = util.cookies.get('token') if (token) { @@ -53,15 +54,23 @@ function webSocketOnMessage (e) { duration: 0 }) } else { - console.log(data.content) - return data + const { content } = data + if (content.model === 'message_center') { + const unread = content.unread + store.dispatch('d2admin/messagecenter/setUnread',unread) + } } } // 关闭websiocket function closeWebsocket () { console.log('连接已关闭...') - // close() - this.socket.close() + ElementUI.Notification({ + title: 'websocket', + message: '连接已关闭...', + type: 'danger', + position: 'bottom-right', + duration: 3000 + }) } /** @@ -72,5 +81,5 @@ function webSocketSend (message) { this.socket.send(JSON.stringify(message)) } export default { - initWebSocket, closeWebsocket, webSocketSend,webSocketOnMessage + initWebSocket, closeWebsocket, webSocketSend } diff --git a/web/src/layout/header-aside/components/header-message/index.vue b/web/src/layout/header-aside/components/header-message/index.vue index 6c6eab1..1d46f8d 100644 --- a/web/src/layout/header-aside/components/header-message/index.vue +++ b/web/src/layout/header-aside/components/header-message/index.vue @@ -14,8 +14,19 @@ class="d2-ml-0 d2-mr btn-text can-hover" type="text" slot="reference" @click="getList"> + + + @@ -27,23 +38,29 @@