From b5a1e7a3bb31306bb97a16f0ec42e39a205ca85f 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, 6 Nov 2022 00:11:03 +0800 Subject: [PATCH 01/41] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG:=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E8=BD=AF=E5=88=A0=E9=99=A4bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/utils/models.py | 2 +- backend/dvadmin/utils/viewset.py | 6 +----- web/.env | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/backend/dvadmin/utils/models.py b/backend/dvadmin/utils/models.py index 273aeaf..df62b0c 100644 --- a/backend/dvadmin/utils/models.py +++ b/backend/dvadmin/utils/models.py @@ -25,7 +25,7 @@ class SoftDeleteQuerySet(QuerySet): :return: Tuple eg.(3, {'lqModel.Test': 3}) """ if soft_delete: - return self.update(is_deleted=True) + return super(SoftDeleteQuerySet, self).update(is_deleted=True) else: return super(SoftDeleteQuerySet, self).delete() diff --git a/backend/dvadmin/utils/viewset.py b/backend/dvadmin/utils/viewset.py index 30ecc09..f029ad9 100644 --- a/backend/dvadmin/utils/viewset.py +++ b/backend/dvadmin/utils/viewset.py @@ -94,11 +94,7 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi instance = self.get_object() request_data = request.data soft_delete = request_data.get('soft_delete',True) - if soft_delete: - instance.is_deleted = True - instance.save() - else: - self.perform_destroy(instance) + instance.delete(soft_delete=soft_delete) return DetailResponse(data=[], msg="删除成功") diff --git a/web/.env b/web/.env index 4425b6d..4abe4b9 100644 --- a/web/.env +++ b/web/.env @@ -1,7 +1,7 @@ # 所有环境默认 # 页面 title 前缀 -VUE_APP_TITLE=D2Admin +VUE_APP_TITLE=DvAdmin # 网络请求公用地址 VUE_APP_API=/api/ From e9aef6b744e60a9af5e08b5b80348000c978d76a 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, 6 Nov 2022 00:27:02 +0800 Subject: [PATCH 02/41] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG:=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E8=BD=AF=E5=88=A0=E9=99=A4bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/utils/models.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/backend/dvadmin/utils/models.py b/backend/dvadmin/utils/models.py index df62b0c..51ca501 100644 --- a/backend/dvadmin/utils/models.py +++ b/backend/dvadmin/utils/models.py @@ -17,17 +17,8 @@ table_prefix = settings.TABLE_PREFIX # 数据库表名前缀 class SoftDeleteQuerySet(QuerySet): - def delete(self,soft_delete=True): - """ - 重写删除方法 - 当soft_delete为True时表示软删除,则修改删除时间为当前时间,否则直接删除 - :param soft: Boolean 是否软删除,默认是 - :return: Tuple eg.(3, {'lqModel.Test': 3}) - """ - if soft_delete: - return super(SoftDeleteQuerySet, self).update(is_deleted=True) - else: - return super(SoftDeleteQuerySet, self).delete() + pass + @@ -78,8 +69,7 @@ class CoreModel(models.Model): def delete(self, using=None, soft_delete=True, *args, **kwargs): """ - Soft delete object (set its ``is_deleted`` field to True). - Actually delete object if setting ``soft`` to False. + 软删除,根据delete(soft_delete=T/F)来判断 """ if soft_delete: self.is_deleted = True From 2c86ad0450f5e52c6fdb35795a348e639b52e762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Wed, 9 Nov 2022 10:13:11 +0800 Subject: [PATCH 03/41] =?UTF-8?q?=E4=BC=98=E5=8C=96:=20queryset=20?= =?UTF-8?q?=E5=BD=93=E8=BF=9B=E5=85=A5if=E5=88=A4=E6=96=AD=EF=BC=8Cfor?= =?UTF-8?q?=E5=BE=AA=E7=8E=AF=EF=BC=8Cprint=E7=AD=89=EF=BC=8C=E4=BC=9A?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E6=9F=A5=E8=AF=A2=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/views/system_config.py | 6 ++---- backend/dvadmin/system/views/user.py | 3 ++- backend/dvadmin/utils/request_util.py | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/backend/dvadmin/system/views/system_config.py b/backend/dvadmin/system/views/system_config.py index aa97091..cd664d3 100644 --- a/backend/dvadmin/system/views/system_config.py +++ b/backend/dvadmin/system/views/system_config.py @@ -108,10 +108,8 @@ class SystemConfigChinldernSerializer(CustomModelSerializer): def get_chinldern(self, instance): queryset = SystemConfig.objects.filter(parent=instance) - if queryset: - serializer = SystemConfigSerializer(queryset, many=True) - return serializer.data - return None + serializer = SystemConfigSerializer(queryset, many=True) + return serializer.data class Meta: model = SystemConfig diff --git a/backend/dvadmin/system/views/user.py b/backend/dvadmin/system/views/user.py index b036370..f5f7d0c 100644 --- a/backend/dvadmin/system/views/user.py +++ b/backend/dvadmin/system/views/user.py @@ -231,7 +231,8 @@ class UserViewSet(CustomModelViewSet): update_serializer_class = UserUpdateSerializer # filter_fields = ["name", "username", "gender", "is_active", "dept", "user_type"] filter_fields = { - "name": ["icontains"], + "name": ["exact"], + "mobile": ["exact"], "username": ["exact"], "gender": ["icontains"], "is_active": ["icontains"], diff --git a/backend/dvadmin/utils/request_util.py b/backend/dvadmin/utils/request_util.py index a964993..a87ac27 100644 --- a/backend/dvadmin/utils/request_util.py +++ b/backend/dvadmin/utils/request_util.py @@ -154,7 +154,7 @@ def get_verbose_name(queryset=None, view=None, model=None): :return: """ try: - if queryset and hasattr(queryset, 'model'): + if queryset is not None and hasattr(queryset, 'model'): model = queryset.model elif view and hasattr(view.get_queryset(), 'model'): model = view.get_queryset().model From 6371c983fb6ae1708359b380ed4f9ef482aa60dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Wed, 9 Nov 2022 10:23:07 +0800 Subject: [PATCH 04/41] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG:=20=E5=85=B3?= =?UTF-8?q?=E4=BA=8E=E5=AF=BC=E5=85=A5=E6=97=B6=E4=B8=8D=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=A1=AB=E5=86=99=E9=83=A8=E9=97=A8=E5=92=8C=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E4=BA=BA=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8Cfix:=20https://git?= =?UTF-8?q?ee.com/liqianglog/django-vue-admin/issues/I5E4LT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/utils/import_export_mixin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/dvadmin/utils/import_export_mixin.py b/backend/dvadmin/utils/import_export_mixin.py index f15e304..1936624 100644 --- a/backend/dvadmin/utils/import_export_mixin.py +++ b/backend/dvadmin/utils/import_export_mixin.py @@ -157,7 +157,7 @@ class ImportSerializerMixin: continue if not filter_dic: instance = None - serializer = self.import_serializer_class(instance, data=ele) + serializer = self.import_serializer_class(instance, data=ele, request=request) serializer.is_valid(raise_exception=True) serializer.save() return DetailResponse(msg=f"导入成功!") @@ -216,7 +216,7 @@ class ExportSerializerMixin: queryset = self.filter_queryset(self.get_queryset()) assert self.export_field_label, "'%s' 请配置对应的导出模板字段。" % self.__class__.__name__ assert self.export_serializer_class, "'%s' 请配置对应的导出序列化器。" % self.__class__.__name__ - data = self.export_serializer_class(queryset, many=True).data + data = self.export_serializer_class(queryset, many=True, request=request).data # 导出excel 表 response = HttpResponse(content_type="application/msexcel") response["Access-Control-Expose-Headers"] = f"Content-Disposition" From fb69352849dfac0810d041d6017278b39b29d040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Wed, 9 Nov 2022 10:38:13 +0800 Subject: [PATCH 05/41] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8F=98=E5=8C=96:=20?= =?UTF-8?q?=E5=9C=B0=E5=8C=BA=E7=AE=A1=E7=90=86=E6=90=9C=E7=B4=A2=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6=E8=BF=87=E6=BB=A4=EF=BC=8Cfix:=20https://gitee.com/li?= =?UTF-8?q?qianglog/django-vue-admin/issues/I5GCS5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/views/system/areas/api.js | 3 ++- web/src/views/system/areas/crud.js | 18 ------------------ 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/web/src/views/system/areas/api.js b/web/src/views/system/areas/api.js index 886fc77..7391a4b 100644 --- a/web/src/views/system/areas/api.js +++ b/web/src/views/system/areas/api.js @@ -3,8 +3,9 @@ import { request } from '@/api/service' export const urlPrefix = '/api/system/area/' export function GetList (query) { - if (query.pcode === undefined || query.pcode === null || query.pcode.length === 0) { + if ((!query.pcode || query.pcode.length === 0) && !query.name && !query.code) { query.level = 1 + delete query.pcode } return request({ url: urlPrefix, diff --git a/web/src/views/system/areas/crud.js b/web/src/views/system/areas/crud.js index 7a00b91..c7a0092 100644 --- a/web/src/views/system/areas/crud.js +++ b/web/src/views/system/areas/crud.js @@ -70,24 +70,6 @@ export const crudOptions = (vm) => { width: 100 }, columns: [ - { - title: '关键词', - key: 'search', - show: false, - disabled: true, - search: { - disabled: false - }, - form: { - disabled: true, - component: { - placeholder: '请输入关键词' - } - }, - view: { - disabled: true - } - }, { title: 'ID', key: 'id', From 74f7a37c1778e8899512461bcbf80a650ed26a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Wed, 9 Nov 2022 11:22:39 +0800 Subject: [PATCH 06/41] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG:=20filter=5Ffields?= =?UTF-8?q?=E4=BD=BF=E7=94=A8icontains=E5=AF=BC=E8=87=B4=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=A4=B1=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/utils/filters.py | 5 ----- web/src/views/system/user/crud.js | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/backend/dvadmin/utils/filters.py b/backend/dvadmin/utils/filters.py index 6fc6912..4e157be 100644 --- a/backend/dvadmin/utils/filters.py +++ b/backend/dvadmin/utils/filters.py @@ -292,11 +292,6 @@ class CustomDjangoFilterBackend(DjangoFilterBackend): ) else: orm_lookups.append(search_field) - orm_lookups = ( - orm_lookups - if isinstance(filterset.__class__._meta.fields, (list, tuple)) - else filterset.filters.keys() - ) conditions = [] queries = [] for search_term_key in filterset.data.keys(): diff --git a/web/src/views/system/user/crud.js b/web/src/views/system/user/crud.js index 59939e4..b63a129 100644 --- a/web/src/views/system/user/crud.js +++ b/web/src/views/system/user/crud.js @@ -210,7 +210,7 @@ export const crudOptions = (vm) => { title: '手机号码', key: 'mobile', search: { - disabled: true + disabled: false }, minWidth: 110, type: 'input', From 54e2ccb380cdfc3c7bfc639b65fc20b219b5c8e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Thu, 10 Nov 2022 00:41:47 +0800 Subject: [PATCH 07/41] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E7=94=A8=E6=88=B7=E7=99=BB=E5=BD=95=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py index 4b08bf2..d04326b 100644 --- a/backend/dvadmin/system/models.py +++ b/backend/dvadmin/system/models.py @@ -387,7 +387,7 @@ class SystemConfig(CoreModel): class LoginLog(CoreModel): - LOGIN_TYPE_CHOICES = ((1, "普通登录"),) + LOGIN_TYPE_CHOICES = ((1, "普通登录"), (2, "微信扫码登录"),) username = models.CharField(max_length=32, verbose_name="登录用户名", null=True, blank=True, help_text="登录用户名") ip = models.CharField(max_length=32, verbose_name="登录ip", null=True, blank=True, help_text="登录ip") agent = models.TextField(verbose_name="agent信息", null=True, blank=True, help_text="agent信息") From 953eb9d6798fca2fca37e20f2cfae8f5da01ea2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Thu, 10 Nov 2022 01:59:40 +0800 Subject: [PATCH 08/41] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8F=98=E5=8C=96:=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20Dockerfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker_env/django/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker_env/django/Dockerfile b/docker_env/django/Dockerfile index 78547c7..e905135 100644 --- a/docker_env/django/Dockerfile +++ b/docker_env/django/Dockerfile @@ -3,4 +3,4 @@ WORKDIR /backend COPY ./backend/ . RUN awk 'BEGIN { cmd="cp -i ./conf/env.example.py ./conf/env.py "; print "n" |cmd; }' RUN python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ -r requirements.txt -CMD ["daphne","-b","0.0.0.0","-p","8000","application.asgi:application"] +CMD ["/dvadmin-backend/docker_start.sh"] From 885156dfb4531b7ff7b38ca24c94f569a8722b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Thu, 10 Nov 2022 02:10:41 +0800 Subject: [PATCH 09/41] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8F=98=E5=8C=96:=20?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20Dockerfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker_env/django/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker_env/django/Dockerfile b/docker_env/django/Dockerfile index e905135..658e46b 100644 --- a/docker_env/django/Dockerfile +++ b/docker_env/django/Dockerfile @@ -3,4 +3,4 @@ WORKDIR /backend COPY ./backend/ . RUN awk 'BEGIN { cmd="cp -i ./conf/env.example.py ./conf/env.py "; print "n" |cmd; }' RUN python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ -r requirements.txt -CMD ["/dvadmin-backend/docker_start.sh"] +CMD ["/backend/docker_start.sh"] From f6115753f8db1ceaad5b9d88e7783d41db67d500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Thu, 10 Nov 2022 03:05:48 +0800 Subject: [PATCH 10/41] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=8F=98=E5=8C=96:=20d?= =?UTF-8?q?ocker-compose.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/docker_start.sh | 3 ++- docker-compose.yml | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/backend/docker_start.sh b/backend/docker_start.sh index 6c75b6c..2654bc1 100755 --- a/backend/docker_start.sh +++ b/backend/docker_start.sh @@ -1,4 +1,5 @@ +#!/bin/bash # python manage.py makemigrations # python manage.py migrate # python manage.py init -y -daphne -b 0.0.0.0 -p 8000 application.asgi:application \ No newline at end of file +daphne -b 0.0.0.0 -p 8000 application.asgi:application diff --git a/docker-compose.yml b/docker-compose.yml index f048298..102aecc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -91,6 +91,27 @@ services: # network: # ipv4_address: 177.8.0.14 + + dvadmin-redis: + image: redis:6.2.6-alpine # 指定服务镜像,最好是与之前下载的redis配置文件保持一致 + container_name: dvadmin-redis # 容器名称 + restart: on-failure # 重启方式 + environment: + - TZ=Asia/Shanghai # 设置时区 + volumes: # 配置数据卷 + - ./docker_env/redis/data:/data + - ./docker_env/redis/redis.conf:/etc/redis/redis.conf + ports: # 映射端口 + - "6379:6379" + sysctls: # 设置容器中的内核参数 + - net.core.somaxconn=1024 + command: /bin/sh -c "echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf && redis-server /etc/redis/redis.conf --appendonly yes" # 指定配置文件并开启持久化 + privileged: true # 使用该参数,container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限 + networks: + network: + ipv4_address: 177.8.0.15 + + networks: network: ipam: 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 11/41] =?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" >