From 4a9a94e04b8d545e564466d1378bee291e36f642 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 16 Jan 2026 14:00:11 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20base=20complexquerymixin=E6=94=AF?= =?UTF-8?q?=E6=8C=81add=5Finfo=5Ffor=5Flist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/utils/mixins.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/utils/mixins.py b/apps/utils/mixins.py index 555fb290..2f7082a6 100755 --- a/apps/utils/mixins.py +++ b/apps/utils/mixins.py @@ -299,7 +299,10 @@ class ComplexQueryMixin: page = self.paginate_queryset(new_qs) if page is not None: serializer = self.get_serializer(page, many=True) - return self.get_paginated_response(serializer.data) + rdata = serializer.data + if hasattr(self, 'add_info_for_list'): + rdata = self.add_info_for_list(rdata) + return self.get_paginated_response(rdata) serializer = self.get_serializer(new_qs, many=True) rdata = serializer.data if hasattr(self, 'add_info_for_list'): From e4fa2561eeb0ec367bace92e9510f344bf8bdf28 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 16 Jan 2026 14:42:42 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20base=20=E5=8D=87=E7=BA=A7=E5=90=8E?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=95=B0=E6=8D=AE=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...reate_by_alter_dept_third_info_and_more.py | 120 ++++++++++++++++++ apps/system/models.py | 8 +- 2 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 apps/system/migrations/0007_alter_dept_create_by_alter_dept_third_info_and_more.py diff --git a/apps/system/migrations/0007_alter_dept_create_by_alter_dept_third_info_and_more.py b/apps/system/migrations/0007_alter_dept_create_by_alter_dept_third_info_and_more.py new file mode 100644 index 00000000..195e4ef8 --- /dev/null +++ b/apps/system/migrations/0007_alter_dept_create_by_alter_dept_third_info_and_more.py @@ -0,0 +1,120 @@ +# Generated by Django 4.2.27 on 2026-01-16 06:41 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0006_auto_20241213_1249'), + ] + + operations = [ + migrations.AlterField( + model_name='dept', + name='create_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'), + ), + migrations.AlterField( + model_name='dept', + name='third_info', + field=models.JSONField(blank=True, default=dict, verbose_name='三方系统信息'), + ), + migrations.AlterField( + model_name='dept', + name='update_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'), + ), + migrations.AlterField( + model_name='dictionary', + name='create_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'), + ), + migrations.AlterField( + model_name='dictionary', + name='update_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'), + ), + migrations.AlterField( + model_name='dicttype', + name='create_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'), + ), + migrations.AlterField( + model_name='dicttype', + name='update_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'), + ), + migrations.AlterField( + model_name='file', + name='create_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'), + ), + migrations.AlterField( + model_name='file', + name='update_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'), + ), + migrations.AlterField( + model_name='myschedule', + name='create_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'), + ), + migrations.AlterField( + model_name='myschedule', + name='update_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'), + ), + migrations.AlterField( + model_name='post', + name='create_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'), + ), + migrations.AlterField( + model_name='post', + name='update_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'), + ), + migrations.AlterField( + model_name='postrole', + name='post', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pr_post', to='system.post', verbose_name='关联岗位'), + ), + migrations.AlterField( + model_name='postrole', + name='role', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pr_role', to='system.role', verbose_name='关联角色'), + ), + migrations.AlterField( + model_name='role', + name='create_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'), + ), + migrations.AlterField( + model_name='role', + name='update_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'), + ), + migrations.AlterField( + model_name='user', + name='belong_dept', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_belong_dept', to='system.dept', verbose_name='所属部门'), + ), + migrations.AlterField( + model_name='user', + name='create_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人'), + ), + migrations.AlterField( + model_name='user', + name='roles', + field=models.ManyToManyField(blank=True, to='system.role', verbose_name='关联角色'), + ), + migrations.AlterField( + model_name='user', + name='update_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'), + ), + ] diff --git a/apps/system/models.py b/apps/system/models.py index 53658e3b..182c1134 100755 --- a/apps/system/models.py +++ b/apps/system/models.py @@ -54,7 +54,7 @@ class Dept(ParentModel, CommonAModel): name = models.CharField('名称', max_length=60) type = models.CharField('类型', max_length=20, default='dept') sort = models.PositiveSmallIntegerField('排序标记', default=1) - third_info = models.JSONField('三方系统信息', default=dict) + third_info = models.JSONField('三方系统信息', default=dict, blank=True) class Meta: verbose_name = '部门' @@ -109,9 +109,9 @@ class PostRole(BaseModel): data_range = models.PositiveSmallIntegerField('数据权限范围', choices=DataFilter.choices, default=DataFilter.THISLEVEL_AND_BELOW) post = models.ForeignKey(Post, verbose_name='关联岗位', - on_delete=models.CASCADE) + on_delete=models.CASCADE, related_name="pr_post") role = models.ForeignKey(Role, verbose_name='关联角色', - on_delete=models.CASCADE) + on_delete=models.CASCADE, related_name='pr_role') class SoftDeletableUserManager(SoftDeletableManagerMixin, UserManager): @@ -134,7 +134,7 @@ class User(AbstractUser, CommonBModel): posts = models.ManyToManyField( Post, through='system.userpost', related_name='user_posts') depts = models.ManyToManyField(Dept, through='system.userpost') - roles = models.ManyToManyField(Role, verbose_name='关联角色') + roles = models.ManyToManyField(Role, verbose_name='关联角色', blank=True) # 关联账号 secret = models.CharField('密钥', max_length=100, null=True, blank=True) From c0064903f4a4a87b7afc04b69fa04bba55ad4b33 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 16 Jan 2026 14:48:08 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20base=20user=E5=A2=9E=E5=8A=A0has=5F?= =?UTF-8?q?perm=E7=AD=9B=E9=80=89=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/system/filters.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/system/filters.py b/apps/system/filters.py index 481b6398..c20c5143 100755 --- a/apps/system/filters.py +++ b/apps/system/filters.py @@ -7,6 +7,7 @@ from rest_framework.exceptions import ParseError class UserFilterSet(filters.FilterSet): ubelong_dept__name = filters.CharFilter(label='归属于该部门及以下(按名称)', method='filter_ubelong_dept__name') ubelong_dept = filters.CharFilter(label='归属于该部门及以下', method='filter_ubelong_dept') + has_perm = filters.CharFilter(label='拥有指定权限标识', method='filter_has_perm') class Meta: model = User @@ -37,6 +38,9 @@ class UserFilterSet(filters.FilterSet): except Exception as e: raise ParseError(f"部门ID错误: {value} {str(e)}") return queryset.filter(belong_dept__in=depts) + + def filter_has_perm(self, queryset, name, value): + return queryset.filter(up_user__post__pr_post__role__perms__codes__contains=value) class DeptFilterSet(filters.FilterSet): From 6d4fc8acbad9d4f0efaa8784b39ecb8ee7a8b102 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 16 Jan 2026 15:10:02 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=E5=90=88=E5=B9=B6migration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/system/migrations/0008_merge_20260116_1509.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 apps/system/migrations/0008_merge_20260116_1509.py diff --git a/apps/system/migrations/0008_merge_20260116_1509.py b/apps/system/migrations/0008_merge_20260116_1509.py new file mode 100644 index 00000000..31d8e167 --- /dev/null +++ b/apps/system/migrations/0008_merge_20260116_1509.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.27 on 2026-01-16 07:09 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0007_alter_dept_create_by_alter_dept_third_info_and_more'), + ('system', '0007_alter_dept_create_by_alter_dept_update_by_and_more'), + ] + + operations = [ + ] From f9584f6a0029e8bc65d2801a3122935fcd19eb24 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 16 Jan 2026 15:11:28 +0800 Subject: [PATCH 5/5] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/asgi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/server/asgi.py b/server/asgi.py index 298f8c4c..e79544df 100755 --- a/server/asgi.py +++ b/server/asgi.py @@ -11,6 +11,7 @@ import os import django from channels.routing import ProtocolTypeRouter, URLRouter +# This is needed for Django to work properly. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'server.settings') django.setup()