From 1b493be828af15950986545f7b39c4eb9b5116c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Sun, 13 Nov 2022 00:53:13 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=96=B0=E5=8A=9F=E8=83=BD:=20=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E4=B8=AD=E5=BF=83crud=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/models.py | 13 +- .../dvadmin/system/views/message_center.py | 94 +++++++++++-- web/src/install.js | 4 + web/src/views/system/messageCenter/crud.js | 104 ++++++++++++-- web/src/views/system/messageCenter/index.vue | 19 ++- .../system/messageCenter/viewTemplate.js | 40 ++++++ web/src/views/system/user/crud.js | 130 +++++++++--------- 7 files changed, 308 insertions(+), 96 deletions(-) create mode 100644 web/src/views/system/messageCenter/viewTemplate.js diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py index d04326b..bb59d12 100644 --- a/backend/dvadmin/system/models.py +++ b/backend/dvadmin/system/models.py @@ -417,15 +417,24 @@ class MessageCenter(CoreModel): title = models.CharField(max_length=100,verbose_name="标题",help_text="标题") content = models.TextField(verbose_name="内容",help_text="内容") target_type=models.IntegerField(default=0,verbose_name="目标类型",help_text="目标类型") - target_user = models.ManyToManyField(to=Users,related_name="target_user",blank=True,db_constraint=False,verbose_name="目标用户",help_text="目标用户") + target_user = models.ManyToManyField(to=Users,related_name='user',through='MessageCenterTargetUser', through_fields=('messagecenter','users'),blank=True,verbose_name="目标用户",help_text="目标用户") target_dept = models.ManyToManyField(to=Dept, blank=True, db_constraint=False, verbose_name="目标部门", help_text="目标部门") target_role = models.ManyToManyField(to=Role, blank=True, db_constraint=False, verbose_name="目标角色", help_text="目标角色") - is_read=models.BooleanField(default=False,blank=True,verbose_name="是否已读",help_text="是否已读") class Meta: db_table = table_prefix + "message_center" verbose_name = "消息中心" verbose_name_plural = verbose_name ordering = ("-create_datetime",) + +class MessageCenterTargetUser(CoreModel): + users = models.ForeignKey(Users,related_name="target_user", on_delete=models.CASCADE,db_constraint=False,verbose_name="关联用户表",help_text="关联用户表") + messagecenter = models.ForeignKey(MessageCenter, on_delete=models.CASCADE,db_constraint=False,verbose_name="关联消息中心表",help_text="关联消息中心表") + is_read = models.BooleanField(default=False,blank=True,null=True,verbose_name="是否已读",help_text="是否已读") + + class Meta: + db_table = table_prefix + "message_center_target_user" + verbose_name = "消息中心目标用户表" + verbose_name_plural = verbose_name \ 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 3571e9c..574f89c 100644 --- a/backend/dvadmin/system/views/message_center.py +++ b/backend/dvadmin/system/views/message_center.py @@ -2,13 +2,15 @@ from itertools import chain 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, AllowAny -from dvadmin.system.models import MessageCenter, Users +from dvadmin.system.models import MessageCenter, Users, MessageCenterTargetUser +from dvadmin.system.views.dept import DeptSerializer from dvadmin.system.views.role import RoleSerializer from dvadmin.system.views.user import UserSerializer -from dvadmin.utils.json_response import SuccessResponse +from dvadmin.utils.json_response import SuccessResponse, DetailResponse from dvadmin.utils.serializers import CustomModelSerializer from dvadmin.utils.viewset import CustomModelViewSet @@ -19,6 +21,8 @@ class MessageCenterSerializer(CustomModelSerializer): """ role_info = DynamicSerializerMethodField() user_info = DynamicSerializerMethodField() + dept_info = DynamicSerializerMethodField() + 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() # You can do what ever you want in here @@ -41,12 +45,49 @@ class MessageCenterSerializer(CustomModelSerializer): ) return serializer.data + def get_dept_info(self, instance, parsed_query): + dept = instance.target_dept.all() + # You can do what ever you want in here + # `parsed_query` param is passed to BookSerializer to allow further querying + serializer = DeptSerializer( + dept, + many=True, + parsed_query=parsed_query + ) + return serializer.data class Meta: model = MessageCenter fields = "__all__" read_only_fields = ["id"] +class MessageCenterTargetUserSerializer(CustomModelSerializer): + """ + 目标用户序列化器-序列化器 + """ + class Meta: + model = MessageCenterTargetUser + fields = "__all__" + read_only_fields = ["id"] + +class MessageCenterTargetUserListSerializer(CustomModelSerializer): + """ + 目标用户序列化器-序列化器 + """ + class Meta: + model = MessageCenterTargetUser + fields = "__all__" + read_only_fields = ["id"] + + def to_representation(self, instance): + data = super().to_representation(instance) + data['title'] = instance.messagecenter.title + data['content'] = instance.messagecenter.content + data['target_type'] = instance.messagecenter.target_type + data['id'] = instance.messagecenter.id + return data + + class MessageCenterCreateSerializer(CustomModelSerializer): """ 消息中心-新增-序列化器 @@ -58,14 +99,21 @@ class MessageCenterCreateSerializer(CustomModelSerializer): target_type = initial_data.get('target_type') # 在保存之前,根据目标类型,把目标用户查询出来并保存 users = initial_data.get('target_user',[]) - if target_type in [1]: + 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]: + 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) - data.save() - data.target_user.set(users) + 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] + targetuser_instance = MessageCenterTargetUserSerializer(data=targetuser_data, many=True, request=self.request) + targetuser_instance.is_valid(raise_exception=True) + targetuser_instance.save() return data class Meta: @@ -90,16 +138,44 @@ class MessageCenterViewSet(CustomModelViewSet): create_serializer_class = MessageCenterCreateSerializer extra_filter_backends = [] + def get_queryset(self): + if self.action=='list': + return MessageCenter.objects.filter(creator=self.request.user.id).all() + return MessageCenter.objects.all() + + def retrieve(self, request, *args, **kwargs): + pk = kwargs.get('pk') + user_id = self.request.user.id + 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) + return DetailResponse(data=serializer.data, msg="获取成功") + + @action(methods=['get'],detail=True,permission_classes=[IsAuthenticated]) + def receive_view(self, request, pk): + """ + 我的接收-查看 + """ + instance = MessageCenterTargetUser.objects.filter(id=pk).first() + instance.is_read = True + instance.save() + serializer = MessageCenterTargetUserListSerializer(instance) + return DetailResponse(data=serializer.data, msg="获取成功") + @action(methods=['GET'],detail=False,permission_classes=[IsAuthenticated]) def get_self_receive(self,request): """ 获取接收到的消息 """ self_user_id = self.request.user.id - queryset = MessageCenter.objects.filter(target_user__id=self_user_id) + queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).exclude(messagecenter__is_deleted=True) + queryset = self.filter_queryset(queryset) page = self.paginate_queryset(queryset) if page is not None: - serializer = self.get_serializer(page, many=True, request=request) + serializer = MessageCenterTargetUserListSerializer(page, many=True, request=request) return self.get_paginated_response(serializer.data) - serializer = self.get_serializer(queryset, many=True, request=request) + serializer = MessageCenterTargetUserListSerializer(queryset, many=True, request=request) return SuccessResponse(data=serializer.data, msg="获取成功") \ No newline at end of file diff --git a/web/src/install.js b/web/src/install.js index 0a42378..429982e 100644 --- a/web/src/install.js +++ b/web/src/install.js @@ -252,6 +252,10 @@ Vue.prototype.commonEndColumns = function (param = {}) { showForm: (param.update_datetime && param.update_datetime.showForm) !== undefined ? param.update_datetime.showForm : false, showTable: (param.update_datetime && param.update_datetime.showTable) !== undefined ? param.update_datetime.showTable : true }, + creator_name: { + showForm: (param.creator_name && param.creator_name.showForm) !== undefined ? param.creator_name.showForm : false, + showTable: (param.creator_name && param.creator_name.showTable) !== undefined ? param.creator_name.showTable : false + }, create_datetime: { showForm: (param.create_datetime && param.create_datetime.showForm) !== undefined ? param.create_datetime.showForm : false, showTable: (param.create_datetime && param.create_datetime.showTable) !== undefined ? param.create_datetime.showTable : true diff --git a/web/src/views/system/messageCenter/crud.js b/web/src/views/system/messageCenter/crud.js index b519444..8c4dd64 100644 --- a/web/src/views/system/messageCenter/crud.js +++ b/web/src/views/system/messageCenter/crud.js @@ -3,13 +3,52 @@ import { request } from '@/api/service' export const crudOptions = (vm) => { return { indexRow: { // 或者直接传true,不显示title,不居中 + width:60, title: '序号', align: 'center' }, options: { + tableType: 'vxe-table', + rowKey: true, // 必须设置,true or false height: '100%' // 表格高度100%, 使用toolbar必须设置 }, - viewOptions: { + rowHandle: { + width: 160, + fixed: 'right', + view: false, + edit: { + thin: true, + text: '', + show () { + return vm.tabActivted !== 'receive' + }, + disabled () { + return !vm.hasPermissions('Update') + } + }, + remove: { + thin: true, + text: '', + show () { + return vm.tabActivted !== 'receive' + }, + disabled () { + return !vm.hasPermissions('Delete') + } + }, + custom: [ + { + thin: true, + text: null, + icon: 'el-icon-view', + size: 'small', + disabled () { + return !vm.hasPermissions('Retrieve') + }, + order: 1, + emit: 'onView' + } + ] }, columns: [ { @@ -24,7 +63,7 @@ export const crudOptions = (vm) => { search: { disabled: false }, - width: 400, + width: 200, form: { rules: [ // 表单校验规则 { @@ -35,12 +74,40 @@ export const crudOptions = (vm) => { component: { span: 24, placeholder: '请输入标题' } } }, + { + title: '是否已读', + key: 'is_read', + type: 'select', + width: 100, + show () { + return vm.tabActivted === 'receive' + }, + dict: { + data: [ + { label: '已读', value: true, color: 'success' }, + { label: '未读', value: false, color: 'danger' } + ] + }, + form: { + disabled: true + } + }, { title: '目标类型', key: 'target_type', type: 'radio', - dict: { data: [{ value: 0, label: '按用户' }, { value: 1, label: '按角色' }, { value: 2, label: '按部门' }] }, + width: 120, + show () { + return vm.tabActivted === 'send' + }, + dict: { data: [{ value: 0, label: '按用户' }, { value: 1, label: '按角色' }, { value: 2, label: '按部门' }, { value: 3, label: '通知公告' }] }, form: { + component: { + span: 24, + props: { + type: 'el-radio-button' + } + }, rules: [ { required: true, @@ -56,8 +123,11 @@ export const crudOptions = (vm) => { search: { disabled: true }, - minWidth: 130, + width: 130, type: 'table-selector', + show () { + return vm.tabActivted === 'send' + }, dict: { cache: false, url: '/api/system/user/', @@ -124,8 +194,10 @@ export const crudOptions = (vm) => { search: { disabled: true }, - - minWidth: 130, + show () { + return vm.tabActivted === 'send' + }, + width: 130, type: 'table-selector', dict: { cache: false, @@ -193,11 +265,14 @@ export const crudOptions = (vm) => { search: { disabled: true }, - minWidth: 130, + width: 130, + show () { + return vm.tabActivted === 'send' + }, type: 'table-selector', dict: { cache: false, - url: '/api/system/dept/', + url: '/api/system/dept/all_dept/', isTree: true, value: 'id', // 数据字典中value字段的属性名 label: 'name', // 数据字典中label字段的属性名 @@ -207,11 +282,7 @@ export const crudOptions = (vm) => { component }) => { return request({ - url: url, - params: { - page: 1, - limit: 999 - } + url: url }).then(ret => { return ret.data.data }) @@ -269,7 +340,7 @@ export const crudOptions = (vm) => { { title: '内容', key: 'content', - width: 300, + minWidth: 300, type: 'editor-quill', // 富文本图片上传依赖file-uploader,请先配置好file-uploader form: { rules: [ // 表单校验规则 @@ -295,6 +366,9 @@ export const crudOptions = (vm) => { } } } - ] + ].concat(vm.commonEndColumns({ + create_datetime: { showTable: true }, + update_datetime: { showTable: false } + })) } } diff --git a/web/src/views/system/messageCenter/index.vue b/web/src/views/system/messageCenter/index.vue index d0f84fe..647a3e4 100644 --- a/web/src/views/system/messageCenter/index.vue +++ b/web/src/views/system/messageCenter/index.vue @@ -5,7 +5,7 @@ ref="d2Crud" v-bind="_crudProps" v-on="_crudListeners" - @form-component-ready="handleFormComponentReady" + @onView="onView" >
@@ -26,9 +26,10 @@