From b28174309a4ac1927ec647443732732fc87ceb0d Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 16 Oct 2024 11:13:25 +0800 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20=E4=BB=8E=E8=BD=A6=E9=97=B4?= =?UTF-8?q?=E5=BA=93=E5=AD=98=E6=98=8E=E7=BB=86=E8=8E=B7=E5=8F=96=E7=89=A9?= =?UTF-8?q?=E6=96=99=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cm/views.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/apps/cm/views.py b/apps/cm/views.py index 0c3952ca..13b0c13d 100644 --- a/apps/cm/views.py +++ b/apps/cm/views.py @@ -1,7 +1,7 @@ from apps.cm.models import LableMat from rest_framework.decorators import action from apps.cm.serializers import TidSerializer, LabelMatSerializer -from apps.inm.models import MaterialBatch +from apps.inm.models import MaterialBatch, MIOItem from apps.wpm.models import WMaterial from rest_framework.exceptions import ParseError, NotFound from rest_framework.response import Response @@ -58,4 +58,27 @@ class LableMatViewSet(CustomListModelMixin, RetrieveModelMixin, CustomGenericVie material_origin=wm.material_origin) rdata = LabelMatSerializer(obj).data rdata["code_label"] = f"mat:{obj.id}" - return Response(rdata) \ No newline at end of file + return Response(rdata) + + @action(methods=['post'], detail=False, serializer_class=TidSerializer) + def get_from_mioitem(self, request, pk=None): + """ + 从出入库明细获取物料标签 + + 从出入库明细获取物料标签 + """ + tid = request.data.get('tid') + try: + mioitem: MIOItem = MIOItem.objects.get(id=tid) + except MIOItem.DoesNotExist: + raise NotFound('出入库明细不存在') + obj, _ = LableMat.objects.get_or_create( + state=10, + material=mioitem.material, + batch=mioitem.batch, + defaults={ + "supplier": mioitem.mio.supplier + }) + rdata = LabelMatSerializer(obj).data + rdata["code_label"] = f"mat:{obj.id}" + return rdata \ No newline at end of file From 7dd39d75bfef4d0a6c8c00bb602b1843a4289705 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 17 Oct 2024 10:28:39 +0800 Subject: [PATCH 02/11] =?UTF-8?q?fix:=20=E7=9B=B8=E5=85=B3=E6=96=B9?= =?UTF-8?q?=E5=88=86=E9=85=8D=E7=AE=A1=E7=90=86=E5=91=98=E9=87=8D=E7=BD=AE?= =?UTF-8?q?=E5=B2=97=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rpm/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/rpm/views.py b/apps/rpm/views.py index 6deef2e5..5358b286 100644 --- a/apps/rpm/views.py +++ b/apps/rpm/views.py @@ -58,7 +58,7 @@ class RpartyViewSet(CustomModelViewSet): 分配账号 """ obj = self.get_object() - post = Post.objects.get(code='remployee') + post = Post.objects.get(code='remployee_m') serializer = RpartyAssignSerializer(data=request.data) serializer.is_valid(raise_exception=True) vdata = serializer.validated_data From deb0cb48df3c4d48861513bbd41483ff9b817475 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 17 Oct 2024 11:12:29 +0800 Subject: [PATCH 03/11] =?UTF-8?q?fix:=20check=5Fremployee=5Fleave=E8=BD=AC?= =?UTF-8?q?task?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rpm/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/rpm/tasks.py b/apps/rpm/tasks.py index 8d314a34..6cc14879 100644 --- a/apps/rpm/tasks.py +++ b/apps/rpm/tasks.py @@ -32,7 +32,7 @@ def close_rpj_by_leave_time(): for m in Rpjmember.objects.filter(rpj__in=rpjs): rpj_member_leave(m) - +@shared_task(base=CustomTask) def check_remployee_leave(): """ 检查相关方是否已经离开 From 27f7b3c07696d2b13f294cf6730b3a8fde6a0d01 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 17 Oct 2024 13:39:45 +0800 Subject: [PATCH 04/11] =?UTF-8?q?feat:=20check=5Fremployee=5Fleave?= =?UTF-8?q?=E8=A7=A6=E5=8F=91=E8=B4=A6=E6=88=B7=E7=A6=81=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rpm/tasks.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/rpm/tasks.py b/apps/rpm/tasks.py index 6cc14879..8b27cb4c 100644 --- a/apps/rpm/tasks.py +++ b/apps/rpm/tasks.py @@ -40,4 +40,9 @@ def check_remployee_leave(): now = datetime.now() now_str = now.strftime('%Y-%m-%d %H:%M:%S') from apps.hrm.models import Employee - Employee.objects.filter(type='remployee', third_info__dh_face_card_end__lte=now_str).update(job_state=Employee.JOB_OFF) \ No newline at end of file + eobjs = Employee.objects.filter(type='remployee', third_info__dh_face_card_end__lte=now_str) + Employee.objects.filter(type='remployee', third_info__dh_face_card_end__lte=now_str).update(job_state=Employee.JOB_OFF) + for e in eobjs: + if e.user: + e.user.is_deleted = True + e.user.save() From f85db52ec7fe1811f45f1d80a7ea3474f33280f9 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 17 Oct 2024 15:55:26 +0800 Subject: [PATCH 05/11] fix: get_from_mioitem bug --- apps/cm/views.py | 49 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/apps/cm/views.py b/apps/cm/views.py index 13b0c13d..f05b6a4c 100644 --- a/apps/cm/views.py +++ b/apps/cm/views.py @@ -8,77 +8,60 @@ from rest_framework.response import Response from apps.utils.viewsets import CustomGenericViewSet, RetrieveModelMixin, CustomListModelMixin # Create your views here. + class LableMatViewSet(CustomListModelMixin, RetrieveModelMixin, CustomGenericViewSet): perms_map = {"post": "*", "get": "*"} serializer_class = LabelMatSerializer queryset = LableMat.objects.all() select_related_fields = ["material", "material_origin", "supplier"] - @action(methods=['post'], detail=False, serializer_class=TidSerializer) + @action(methods=["post"], detail=False, serializer_class=TidSerializer) def get_from_mb(self, request, pk=None): """ 从仓库明细获取物料标签 从仓库明细获取物料标签 """ - tid = request.data.get('tid') + tid = request.data.get("tid") try: mb = MaterialBatch.objects.get(id=tid) except MaterialBatch.DoesNotExist: - raise NotFound('仓库明细不存在') - obj, _ = LableMat.objects.get_or_create( - state=10, - material=mb.material, - batch=mb.batch, - defaults={ - "supplier": mb.supplier - } - ) + raise NotFound("仓库明细不存在") + obj, _ = LableMat.objects.get_or_create(state=10, material=mb.material, batch=mb.batch, defaults={"supplier": mb.supplier}) rdata = LabelMatSerializer(obj).data rdata["code_label"] = f"mat:{obj.id}" return Response(rdata) - - @action(methods=['post'], detail=False, serializer_class=TidSerializer) + + @action(methods=["post"], detail=False, serializer_class=TidSerializer) def get_from_wm(self, request, pk=None): """ 从车间库存明细获取物料标签 从车间库存明细获取物料标签 """ - tid = request.data.get('tid') + tid = request.data.get("tid") try: wm = WMaterial.objects.get(id=tid) except WMaterial.DoesNotExist: - raise NotFound('车间库存不存在') - obj, _ = LableMat.objects.get_or_create( - state=wm.state, - material=wm.material, - batch=wm.batch, - notok_sign=wm.notok_sign, - material_origin=wm.material_origin) + raise NotFound("车间库存不存在") + obj, _ = LableMat.objects.get_or_create(state=wm.state, material=wm.material, batch=wm.batch, notok_sign=wm.notok_sign, material_origin=wm.material_origin) rdata = LabelMatSerializer(obj).data rdata["code_label"] = f"mat:{obj.id}" return Response(rdata) - - @action(methods=['post'], detail=False, serializer_class=TidSerializer) + + @action(methods=["post"], detail=False, serializer_class=TidSerializer) def get_from_mioitem(self, request, pk=None): """ 从出入库明细获取物料标签 从出入库明细获取物料标签 """ - tid = request.data.get('tid') + tid = request.data.get("tid") try: mioitem: MIOItem = MIOItem.objects.get(id=tid) except MIOItem.DoesNotExist: - raise NotFound('出入库明细不存在') - obj, _ = LableMat.objects.get_or_create( - state=10, - material=mioitem.material, - batch=mioitem.batch, - defaults={ - "supplier": mioitem.mio.supplier - }) + raise NotFound("出入库明细不存在") + obj, _ = LableMat.objects.get_or_create(state=10, material=mioitem.material, batch=mioitem.batch, defaults={"supplier": mioitem.mio.supplier}) rdata = LabelMatSerializer(obj).data rdata["code_label"] = f"mat:{obj.id}" - return rdata \ No newline at end of file + return Response(rdata) From abeb70d16655345b14fb1530ed9c28763d46affc Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 18 Oct 2024 09:43:06 +0800 Subject: [PATCH 06/11] =?UTF-8?q?feat:=20develop=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E6=B5=8B=E8=AF=95=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/develop/tasks.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/apps/develop/tasks.py b/apps/develop/tasks.py index 11702a49..4600dee6 100755 --- a/apps/develop/tasks.py +++ b/apps/develop/tasks.py @@ -10,14 +10,11 @@ def backup_database(): 备份数据库 """ import datetime - name = datetime.datetime.now().strftime('%Y%m%d%H%M%S') + + name = datetime.datetime.now().strftime("%Y%m%d%H%M%S") command = 'echo "{}" | sudo -S pg_dump "user={} password={} dbname={}" > {}/bak_{}.sql'.format( - SD_PWD, - DATABASES['default']['USER'], - DATABASES['default']['PASSWORD'], - DATABASES['default']['NAME'], - BACKUP_PATH + '/database', - name) + SD_PWD, DATABASES["default"]["USER"], DATABASES["default"]["PASSWORD"], DATABASES["default"]["NAME"], BACKUP_PATH + "/database", name + ) completed = subprocess.run(command, shell=True, capture_output=True, text=True) if completed.returncode != 0: return completed.stderr @@ -25,7 +22,7 @@ def backup_database(): @shared_task def reload_server_git(): - command = 'bash {}/git_server.sh'.format(SH_PATH) + command = "bash {}/git_server.sh".format(SH_PATH) completed = subprocess.run(command, shell=True, capture_output=True, text=True) if completed.returncode != 0: return completed.stderr @@ -33,7 +30,7 @@ def reload_server_git(): @shared_task def reload_web_git(): - command = 'bash {}/git_web.sh'.format(SH_PATH) + command = "bash {}/git_web.sh".format(SH_PATH) completed = subprocess.run(command, shell=True, capture_output=True, text=True) if completed.returncode != 0: return completed.stderr @@ -48,7 +45,16 @@ def reload_server_only(): @shared_task def backup_media(): - command = 'bash {}/backup_media.sh'.format(SH_PATH) + command = "bash {}/backup_media.sh".format(SH_PATH) completed = subprocess.run(command, shell=True, capture_output=True, text=True) if completed.returncode != 0: return completed.stderr + + +@shared_task +def test_task(): + import time + + while True: + print("test") + time.sleep(10) From ca32d9f20f4f6494515b6ccc1366dcddd7c2ee70 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Sun, 20 Oct 2024 10:46:06 +0800 Subject: [PATCH 07/11] =?UTF-8?q?fix:=20base=20permission=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/utils/permission.py | 17 ++++++----------- apps/utils/viewsets.py | 4 +--- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/apps/utils/permission.py b/apps/utils/permission.py index 0506ebad..d0d19fde 100755 --- a/apps/utils/permission.py +++ b/apps/utils/permission.py @@ -13,7 +13,7 @@ ALL_PERMS = [ # 数据库里定义的权限标识 def get_alld_perms(update_cache=False) -> List[str]: key = "perms_alld_list" - perms_alld_list = cache.get(key) + perms_alld_list = cache.get(key, None) if perms_alld_list is None or update_cache: nested_list = Permission.objects.all().values_list('codes', flat=True) perms_alld_list = list(set([item for sublist in nested_list for item in sublist])) @@ -26,7 +26,8 @@ def get_user_perms_map(user, update_cache=False): 获取权限字典,可用redis存取(包括功能和数据权限) """ key = f'perms_{str(user.id)}' - if cache.get(key) is None or update_cache: + user_perms_map = cache.get(key, None) + if user_perms_map is None or update_cache: user_perms_map = {} if user.is_superuser: codes = get_alld_perms() @@ -58,9 +59,7 @@ def has_perm(user: User, perm_codes: List[str]): """ 返回用户是否具有给定权限列表中的权限 """ - user_perms_map = cache.get(f'perms_{user.id}', None) - if user_perms_map is None: - user_perms_map = get_user_perms_map(user) + user_perms_map = get_user_perms_map(user) for item in perm_codes: if item in user_perms_map: return True @@ -81,9 +80,7 @@ class RbacPermission(BasePermission): """ if not hasattr(view, 'perms_map'): return True - user_perms_map = cache.get('perms_' + request.user.id, None) - if user_perms_map is None: - user_perms_map = get_user_perms_map(request.user) + user_perms_map = get_user_perms_map(request.user) if isinstance(user_perms_map, dict): perms_map = view.perms_map _method = request._request.method.lower() @@ -125,9 +122,7 @@ class RbacDataMixin: if hasattr(queryset.model, 'belong_dept'): user = self.request.user - user_perms_map = cache.get('perms_' + user.id, None) - if user_perms_map is None: - user_perms_map = get_user_perms_map(self.request.user) + user_perms_map = get_user_perms_map(self.request.user) if isinstance(user_perms_map, dict): if hasattr(self.view, 'perms_map'): perms_map = self.view.perms_map diff --git a/apps/utils/viewsets.py b/apps/utils/viewsets.py index 0d816a0a..b8bb0785 100755 --- a/apps/utils/viewsets.py +++ b/apps/utils/viewsets.py @@ -116,9 +116,7 @@ class CustomGenericViewSet(MyLoggingMixin, GenericViewSet): user = self.request.user if user.is_superuser: return queryset - user_perms_map = cache.get('perms_' + str(user.id), None) - if user_perms_map is None: - user_perms_map = get_user_perms_map(self.request.user) + user_perms_map = get_user_perms_map(self.request.user) if isinstance(user_perms_map, dict): if hasattr(self, 'perms_map'): perms_map = self.perms_map From 7b34ddd70c4db364428bc12baebbac707bd53c67 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Sat, 19 Oct 2024 21:00:43 +0800 Subject: [PATCH 08/11] =?UTF-8?q?fix:=20=E7=B3=BB=E7=BB=9F=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E6=97=B6=E4=B8=8D=E5=BF=85=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E6=9D=83=E9=99=90=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/system/apps.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/system/apps.py b/apps/system/apps.py index bf6e73d0..59d27b05 100755 --- a/apps/system/apps.py +++ b/apps/system/apps.py @@ -12,10 +12,4 @@ class SystemConfig(AppConfig): from server.settings import get_sysconfig get_sysconfig(reload=True) cache.set('cache_sysconfig_need_task', False, timeout=30) - - if cache.get('cache_alldperms_task', True): - from apps.utils.permission import get_alld_perms - get_alld_perms(update_cache=True) - cache.set('cache_alldperms_task', False, timeout=30) - return super().ready() From 3343d30f772ddb9f210ec6873299c405cd59eca9 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 22 Oct 2024 08:28:04 +0800 Subject: [PATCH 09/11] =?UTF-8?q?feat:=20develop=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/develop/tasks.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/develop/tasks.py b/apps/develop/tasks.py index 4600dee6..13d4ddd1 100755 --- a/apps/develop/tasks.py +++ b/apps/develop/tasks.py @@ -54,7 +54,8 @@ def backup_media(): @shared_task def test_task(): import time - - while True: - print("test") - time.sleep(10) + x = 1 + while x < 300: + print(f"test_{x}") + time.sleep(1) + x += 1 From d4dc94df892cf343bbf7b09e1d2093aa6b4d0144 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 23 Oct 2024 16:30:28 +0800 Subject: [PATCH 10/11] =?UTF-8?q?feat:=20edu=20paper=E6=B7=BB=E5=8A=A0type?= =?UTF-8?q?=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/edu/migrations/0004_paper_type.py | 18 +++ apps/edu/models.py | 159 +++++++++++++------------ 2 files changed, 103 insertions(+), 74 deletions(-) create mode 100644 apps/edu/migrations/0004_paper_type.py diff --git a/apps/edu/migrations/0004_paper_type.py b/apps/edu/migrations/0004_paper_type.py new file mode 100644 index 00000000..05e622ff --- /dev/null +++ b/apps/edu/migrations/0004_paper_type.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2024-10-23 08:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('edu', '0003_alter_train_level'), + ] + + operations = [ + migrations.AddField( + model_name='paper', + name='type', + field=models.PositiveSmallIntegerField(choices=[(10, '固定试卷'), (20, '随机试卷')], default=10, verbose_name='类型'), + ), + ] diff --git a/apps/edu/models.py b/apps/edu/models.py index cee77945..952f09c4 100644 --- a/apps/edu/models.py +++ b/apps/edu/models.py @@ -4,39 +4,41 @@ from apps.system.models import User, Dept, File # Create your models here. -class Train(CommonADModel): +class Train(CommonADModel): T_L_POST = 10 T_L_TEAM = 20 T_L_DEPT = 30 T_L_COMPANY = 40 - level = models.PositiveSmallIntegerField(verbose_name='级别', choices=((T_L_POST, '岗位'), (T_L_TEAM, '班组'), (T_L_DEPT, '部门'), (T_L_COMPANY, '公司'))) - name = models.CharField(max_length=200, verbose_name='名称') - place = models.CharField(max_length=200, verbose_name='地点', default='', blank=True) - start_time = models.DateTimeField(verbose_name='开始时间') - end_time = models.DateTimeField(verbose_name='结束时间') - duration = models.PositiveIntegerField(verbose_name='时长', default=0, help_text='单位:s', editable=False) - description = models.TextField(verbose_name='内容描述', default='', blank=True) - is_public = models.BooleanField('是否公开', default=False) - files = models.ManyToManyField(File, verbose_name='附件', blank=True) - + level = models.PositiveSmallIntegerField(verbose_name="级别", choices=((T_L_POST, "岗位"), (T_L_TEAM, "班组"), (T_L_DEPT, "部门"), (T_L_COMPANY, "公司"))) + name = models.CharField(max_length=200, verbose_name="名称") + place = models.CharField(max_length=200, verbose_name="地点", default="", blank=True) + start_time = models.DateTimeField(verbose_name="开始时间") + end_time = models.DateTimeField(verbose_name="结束时间") + duration = models.PositiveIntegerField(verbose_name="时长", default=0, help_text="单位:s", editable=False) + description = models.TextField(verbose_name="内容描述", default="", blank=True) + is_public = models.BooleanField("是否公开", default=False) + files = models.ManyToManyField(File, verbose_name="附件", blank=True) + class Meta: - verbose_name = '线下培训' + verbose_name = "线下培训" verbose_name_plural = verbose_name + class Questioncat(CommonAModel): - name = models.CharField(max_length=200, verbose_name='名称') - parent = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='父级', related_name='cate_parent') - sort = models.PositiveIntegerField(default=0, verbose_name='排序') + name = models.CharField(max_length=200, verbose_name="名称") + parent = models.ForeignKey("self", on_delete=models.SET_NULL, null=True, blank=True, verbose_name="父级", related_name="cate_parent") + sort = models.PositiveIntegerField(default=0, verbose_name="排序") class Meta: - verbose_name = '题库分类' + verbose_name = "题库分类" verbose_name_plural = verbose_name def __str__(self): return self.name - + + class Question(CommonAModel): Q_DAN = 10 Q_DUO = 20 @@ -44,97 +46,106 @@ class Question(CommonAModel): Q_EASY = 10 Q_SIMPLE = 20 Q_HARD = 30 - name = models.TextField('题干') - img = models.TextField('题干图片', null=True, blank=True) - type = models.PositiveSmallIntegerField('题型', choices=((Q_DAN, '单选'), (Q_DUO, '多选'), (Q_PAN, '判断'))) - level = models.PositiveSmallIntegerField('难度', default=Q_SIMPLE, choices=((Q_EASY, '简单'), (Q_SIMPLE, '一般'), (Q_HARD, '困难'))) - questioncat = models.ForeignKey(Questioncat, blank=True, null=True, on_delete=models.SET_NULL, verbose_name='所属题库', related_name='questioncat') - options = models.JSONField('选项') - right = models.JSONField('正确答案') - resolution = models.TextField('解析', null=True, blank=True) - enabled = models.BooleanField('是否启用', default=False) + name = models.TextField("题干") + img = models.TextField("题干图片", null=True, blank=True) + type = models.PositiveSmallIntegerField("题型", choices=((Q_DAN, "单选"), (Q_DUO, "多选"), (Q_PAN, "判断"))) + level = models.PositiveSmallIntegerField("难度", default=Q_SIMPLE, choices=((Q_EASY, "简单"), (Q_SIMPLE, "一般"), (Q_HARD, "困难"))) + questioncat = models.ForeignKey(Questioncat, blank=True, null=True, on_delete=models.SET_NULL, verbose_name="所属题库", related_name="questioncat") + options = models.JSONField("选项") + right = models.JSONField("正确答案") + resolution = models.TextField("解析", null=True, blank=True) + enabled = models.BooleanField("是否启用", default=False) + class Meta: - verbose_name = '题目' + verbose_name = "题目" verbose_name_plural = verbose_name def __str__(self): return self.name - + class Paper(CommonAModel): - name = models.CharField(max_length=200, verbose_name='名称') - questions = models.ManyToManyField(Question, through='PaperQuestion') - limit = models.IntegerField(default=0, verbose_name='限时(分钟)') - total_score = models.FloatField(default=0, verbose_name='满分') - pass_score = models.FloatField(default=0, verbose_name='通过分数') - danxuan_count = models.IntegerField(default=0, verbose_name='单选数量') - danxuan_score = models.FloatField(default=2, verbose_name='单选分数') - duoxuan_count = models.IntegerField(default=0, verbose_name='多选数量') - duoxuan_score = models.FloatField(default=4, verbose_name='多选分数') - panduan_count = models.IntegerField(default=0, verbose_name='判断数量') - panduan_score = models.FloatField(default=2, verbose_name='判断分数') + PAPER_FIX = 10 # 固定试卷 + PAPER_RANDOM = 20 # 自动抽题 + + name = models.CharField(max_length=200, verbose_name="名称") + type = models.PositiveSmallIntegerField("类型", default=10, choices=((PAPER_FIX, "固定试卷"), (PAPER_RANDOM, "随机试卷"))) + questions = models.ManyToManyField(Question, through="PaperQuestion") + limit = models.IntegerField(default=0, verbose_name="限时(分钟)") + total_score = models.FloatField(default=0, verbose_name="满分") + pass_score = models.FloatField(default=0, verbose_name="通过分数") + danxuan_count = models.IntegerField(default=0, verbose_name="单选数量") + danxuan_score = models.FloatField(default=2, verbose_name="单选分数") + duoxuan_count = models.IntegerField(default=0, verbose_name="多选数量") + duoxuan_score = models.FloatField(default=4, verbose_name="多选分数") + panduan_count = models.IntegerField(default=0, verbose_name="判断数量") + panduan_score = models.FloatField(default=2, verbose_name="判断分数") + class Meta: - verbose_name = '押题卷' + verbose_name = "押题卷" verbose_name_plural = verbose_name def __str__(self): return self.name - + @property def detail(self): return PaperQuestion.objects.filter(paper=self) + class PaperQuestion(BaseModel): - paper = models.ForeignKey(Paper, on_delete=models.CASCADE, verbose_name='试卷') - question = models.ForeignKey(Question, on_delete=models.CASCADE, verbose_name='试题') - total_score = models.FloatField(default=0, verbose_name='单题满分') - sort = models.IntegerField(default=0, verbose_name='排序') + paper = models.ForeignKey(Paper, on_delete=models.CASCADE, verbose_name="试卷") + question = models.ForeignKey(Question, on_delete=models.CASCADE, verbose_name="试题") + total_score = models.FloatField(default=0, verbose_name="单题满分") + sort = models.IntegerField(default=0, verbose_name="排序") class Exam(CommonADModel): - name = models.CharField('名称', max_length=100) - open_time = models.DateTimeField('开启时间') - close_time = models.DateTimeField('关闭时间', null=True, blank=True) - chance = models.IntegerField('考试机会', default=1) # 0表示不限次数 - paper = models.ForeignKey(Paper, verbose_name='使用的试卷', on_delete=models.SET_NULL, null=True, blank=True) - is_public = models.BooleanField('是否公开', default=False) - p_users = models.ManyToManyField(User, verbose_name='指定用户', blank=True) - p_depts = models.ManyToManyField(Dept, verbose_name='指定部门', blank=True) + name = models.CharField("名称", max_length=100) + open_time = models.DateTimeField("开启时间") + close_time = models.DateTimeField("关闭时间", null=True, blank=True) + chance = models.IntegerField("考试机会", default=1) # 0表示不限次数 + paper = models.ForeignKey(Paper, verbose_name="使用的试卷", on_delete=models.SET_NULL, null=True, blank=True) + is_public = models.BooleanField("是否公开", default=False) + p_users = models.ManyToManyField(User, verbose_name="指定用户", blank=True) + p_depts = models.ManyToManyField(Dept, verbose_name="指定部门", blank=True) class Meta: - verbose_name = '在线考试' + verbose_name = "在线考试" verbose_name_plural = verbose_name def __str__(self): return self.name + class ExamRecord(CommonADModel): - ''' + """ 考试记录表 - ''' - exam = models.ForeignKey(Exam, on_delete=models.CASCADE, verbose_name='关联考试', related_name='record_exam') - score = models.FloatField(default=0, verbose_name='得分') - took = models.IntegerField(default=0, verbose_name='耗时(秒)') - start_time = models.DateTimeField(verbose_name='开始答题时间') - end_time = models.DateTimeField(verbose_name='结束答题时间', null=True, blank=True) - questions = models.ManyToManyField(Question, verbose_name='答题记录', through='AnswerDetail') - is_pass = models.BooleanField(default=True, verbose_name='是否通过') - is_submited = models.BooleanField(default=False, verbose_name='是否提交') - is_last = models.BooleanField(default=False, verbose_name='是否最后一次考试记录') - + """ + + exam = models.ForeignKey(Exam, on_delete=models.CASCADE, verbose_name="关联考试", related_name="record_exam") + score = models.FloatField(default=0, verbose_name="得分") + took = models.IntegerField(default=0, verbose_name="耗时(秒)") + start_time = models.DateTimeField(verbose_name="开始答题时间") + end_time = models.DateTimeField(verbose_name="结束答题时间", null=True, blank=True) + questions = models.ManyToManyField(Question, verbose_name="答题记录", through="AnswerDetail") + is_pass = models.BooleanField(default=True, verbose_name="是否通过") + is_submited = models.BooleanField(default=False, verbose_name="是否提交") + is_last = models.BooleanField(default=False, verbose_name="是否最后一次考试记录") + class Meta: - verbose_name = '考试记录' + verbose_name = "考试记录" verbose_name_plural = verbose_name class AnswerDetail(BaseModel): - examrecord = models.ForeignKey(ExamRecord, on_delete=models.CASCADE, related_name='detail_er') - total_score = models.FloatField(default=0, verbose_name='该题满分') + examrecord = models.ForeignKey(ExamRecord, on_delete=models.CASCADE, related_name="detail_er") + total_score = models.FloatField(default=0, verbose_name="该题满分") question = models.ForeignKey(Question, on_delete=models.CASCADE) - user_answer = models.JSONField(null=True,blank=True) - score = models.FloatField(default=0, verbose_name='本题得分') - is_right = models.BooleanField(default=False, verbose_name='是否正确') + user_answer = models.JSONField(null=True, blank=True) + score = models.FloatField(default=0, verbose_name="本题得分") + is_right = models.BooleanField(default=False, verbose_name="是否正确") class Meta: - verbose_name = '答题记录' - verbose_name_plural = verbose_name \ No newline at end of file + verbose_name = "答题记录" + verbose_name_plural = verbose_name From 8d6939a4fcfe6b508d852b22dfd1fb3299c63cc9 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 23 Oct 2024 17:07:52 +0800 Subject: [PATCH 11/11] =?UTF-8?q?feat:=20base=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E6=9D=83=E9=99=90=E6=97=B6=E4=BB=85=E5=A4=B1?= =?UTF-8?q?=E6=95=88=E7=BC=93=E5=AD=98=E5=8D=B3=E5=8F=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/system/views.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/apps/system/views.py b/apps/system/views.py index c14b26c1..ce92f414 100755 --- a/apps/system/views.py +++ b/apps/system/views.py @@ -1,5 +1,3 @@ -import configparser -import os import importlib import json from drf_yasg import openapi @@ -24,7 +22,7 @@ from apps.system.filters import DeptFilterSet, UserFilterSet # from django_q.models import Task as QTask, Schedule as QSchedule from apps.utils.mixins import (CustomCreateModelMixin, MyLoggingMixin) from django.conf import settings -from apps.utils.permission import ALL_PERMS, get_user_perms_map, get_alld_perms +from apps.utils.permission import ALL_PERMS, get_user_perms_map from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet from server.celery import app as celery_app from .models import (Dept, Dictionary, DictType, File, Permission, Post, PostRole, Role, User, @@ -44,7 +42,7 @@ import locale from drf_yasg.utils import swagger_auto_schema from server.settings import get_sysconfig, update_sysconfig, update_dict from apps.utils.constants import DEFAULT_PWD -from apps.utils.thread import MyThread +from django.core.cache import cache # logger.info('请求成功! response_code:{};response_headers:{}; # response_body:{}'.format(response_code, response_headers, response_body[:251])) @@ -321,15 +319,15 @@ class PermissionViewSet(CustomModelViewSet): def perform_create(self, serializer): super().perform_create(serializer) - MyThread(target=get_alld_perms, kwargs={"update_cache": True}).start_p() + cache.delete('perms_alld_list') def perform_update(self, serializer): super().perform_update(serializer) - MyThread(target=get_alld_perms, kwargs={"update_cache": True}).start_p() + cache.delete('perms_alld_list') def perform_destroy(self, instance): super().perform_destroy(instance) - MyThread(target=get_alld_perms, kwargs={"update_cache": True}).start_p() + cache.delete('perms_alld_list') class DeptViewSet(CustomModelViewSet): """部门-增删改查