From 6de96ce19a64a7bb1824bedee27c8586af2b1b1d Mon Sep 17 00:00:00 2001 From: zty Date: Thu, 30 May 2024 17:46:53 +0800 Subject: [PATCH 01/38] =?UTF-8?q?:fix=EF=BC=9A=E4=BF=AE=E6=94=B9=E9=A2=98?= =?UTF-8?q?=E7=9B=AE=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/apps/exam/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/apps/exam/views.py b/server/apps/exam/views.py index 8a2df89..fe6e689 100644 --- a/server/apps/exam/views.py +++ b/server/apps/exam/views.py @@ -610,7 +610,7 @@ class ExamRecordViewSet(ListModelMixin, DestroyModelMixin, RetrieveModelMixin, G er.took = (now - er.create_time).total_seconds() er.end_time = now - er.belong_dept=request.user.dept.id + er.belong_dept=request.user.dept er.is_submited = True er.save() return Response(ExamRecordListSerializer(instance=er).data) \ No newline at end of file From fde4bdf0ea70fe1401348a612cd232f6a3c430cb Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 31 May 2024 10:23:20 +0800 Subject: [PATCH 02/38] =?UTF-8?q?feat:=20=E8=80=83=E8=AF=95=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/apps/exam/filters.py | 10 +++++++++- server/apps/exam/views.py | 31 ++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/server/apps/exam/filters.py b/server/apps/exam/filters.py index 8b14f43..4f077e6 100644 --- a/server/apps/exam/filters.py +++ b/server/apps/exam/filters.py @@ -1,4 +1,5 @@ from django_filters import rest_framework as filters +from django.utils import timezone from .models import ExamRecord, Exam class ExamRecordFilter(filters.FilterSet): class Meta: @@ -11,6 +12,7 @@ class ExamRecordFilter(filters.FilterSet): } class ExamFilter(filters.FilterSet): + can_attend = filters.BooleanFilter(method='filter_can_attend') class Meta: model = Exam fields = { @@ -18,4 +20,10 @@ class ExamFilter(filters.FilterSet): 'paper': ['exact'], 'code': ['exact'], 'is_open': ['exact'] - } \ No newline at end of file + } + + def filter_can_attend(self, queryset, name, value): + if value: + now = timezone.now() + return queryset.filter(open_time__lte=now, close_time__gte=now)| queryset.filter(close_time__isnull=True) + return queryset \ No newline at end of file diff --git a/server/apps/exam/views.py b/server/apps/exam/views.py index fe6e689..188b43e 100644 --- a/server/apps/exam/views.py +++ b/server/apps/exam/views.py @@ -25,6 +25,7 @@ from apps.system.permission import has_permission from apps.exam.parse_word import interpret_text import os import shutil +from django.db.models import Q # Create your views here. EXCEL_PATH = os.path.join(settings.BASE_DIR, "media/default/question.xlsx") @@ -412,7 +413,7 @@ class PaperViewSet(ModelViewSet): class ExamViewSet(CreateUpdateCustomMixin, ModelViewSet): - perms_map = {'get': '*', 'post':'exam', 'put':'exam', 'delete':'exam'} + perms_map = {'get': 'exam', 'post':'exam', 'put':'exam', 'delete':'exam'} queryset = Exam.objects.all().select_related('paper', 'create_by') ordering = ['-id'] search_fields = ('name',) @@ -425,6 +426,24 @@ class ExamViewSet(CreateUpdateCustomMixin, ModelViewSet): elif self.action in ['retrieve']: return ExamDetailSerializer return super().get_serializer_class() + + @action(methods=['get'], detail=False, permission_classes=[IsAuthenticated]) + def self(self, request, pk=None): + ''' + 跟我有关的考试 + + 跟我有关的考试 + ''' + queryset = self.get_queryset().filter(Q(participant_user=request.user)|Q(participant_dep=request.user.dept)) + queryset = self.filter_queryset(queryset) + + page = self.paginate_queryset(queryset) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(queryset, many=True) + return Response(serializer.data) def destroy(self, request, *args, **kwargs): instance = self.get_object() @@ -538,9 +557,15 @@ class ExamRecordViewSet(ListModelMixin, DestroyModelMixin, RetrieveModelMixin, G 个人考试记录 ''' queryset = ExamRecord.objects.filter(create_by=request.user).order_by('-update_time') + queryset = self.filter_queryset(queryset) + page = self.paginate_queryset(queryset) - serializer = self.get_serializer(page, many=True) - return self.get_paginated_response(serializer.data) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(queryset, many=True) + return Response(serializer.data) @action(methods=['post'], detail=True, perms_map=[{'post': '*'}], serializer_class=ExamRecordSubmitSerializer, permission_classes = [IsAuthenticated]) @transaction.atomic From 527496094531baf76769abfd2d97c9858f055379 Mon Sep 17 00:00:00 2001 From: zty Date: Fri, 31 May 2024 11:03:01 +0800 Subject: [PATCH 03/38] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E4=B8=AA?= =?UTF-8?q?=E4=BA=BA=E8=80=83=E8=AF=95=E8=AE=B0=E5=BD=95=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=92=8C=E4=B8=AA=E4=BA=BA=E5=8F=82=E4=B8=8E=E8=80=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/apps/exam/filters.py | 17 ++++++++++++++- server/apps/exam/views.py | 41 +++++++------------------------------ 2 files changed, 23 insertions(+), 35 deletions(-) diff --git a/server/apps/exam/filters.py b/server/apps/exam/filters.py index 4f077e6..9d85eae 100644 --- a/server/apps/exam/filters.py +++ b/server/apps/exam/filters.py @@ -1,7 +1,9 @@ from django_filters import rest_framework as filters from django.utils import timezone from .models import ExamRecord, Exam +from django.db.models import Q class ExamRecordFilter(filters.FilterSet): + is_my = filters.BooleanFilter(method='filter_is_my') class Meta: model = ExamRecord fields = { @@ -10,9 +12,15 @@ class ExamRecordFilter(filters.FilterSet): 'type': ['exact'], 'is_submited': ['exact'], } + def filter_is_my(self, queryset, name, value): + if value: + user = self.request.user + return queryset.filter(create_by=user) + return queryset class ExamFilter(filters.FilterSet): can_attend = filters.BooleanFilter(method='filter_can_attend') + is_my = filters.BooleanFilter(method='filter_is_my') class Meta: model = Exam fields = { @@ -26,4 +34,11 @@ class ExamFilter(filters.FilterSet): if value: now = timezone.now() return queryset.filter(open_time__lte=now, close_time__gte=now)| queryset.filter(close_time__isnull=True) - return queryset \ No newline at end of file + return queryset + + def filter_is_my(self, queryset, name, value): + if value: + user = self.request.user + return queryset.filter(Q(participant_user=user)|Q(participant_dep=user.dept)|Q(is_open=True)) + return queryset + \ No newline at end of file diff --git a/server/apps/exam/views.py b/server/apps/exam/views.py index 188b43e..a37e6b4 100644 --- a/server/apps/exam/views.py +++ b/server/apps/exam/views.py @@ -413,7 +413,7 @@ class PaperViewSet(ModelViewSet): class ExamViewSet(CreateUpdateCustomMixin, ModelViewSet): - perms_map = {'get': 'exam', 'post':'exam', 'put':'exam', 'delete':'exam'} + perms_map = {'get': '*', 'post':'exam', 'put':'exam', 'delete':'exam'} queryset = Exam.objects.all().select_related('paper', 'create_by') ordering = ['-id'] search_fields = ('name',) @@ -427,23 +427,13 @@ class ExamViewSet(CreateUpdateCustomMixin, ModelViewSet): return ExamDetailSerializer return super().get_serializer_class() - @action(methods=['get'], detail=False, permission_classes=[IsAuthenticated]) - def self(self, request, pk=None): - ''' - 跟我有关的考试 + def get_queryset(self): + qs = super().get_queryset() + user = self.request.user + if has_permission("exam", user): + return qs + return qs.filter(Q(participant_user=user)|Q(participant_dep=user.dept)|Q(is_open=True)) - 跟我有关的考试 - ''' - queryset = self.get_queryset().filter(Q(participant_user=request.user)|Q(participant_dep=request.user.dept)) - queryset = self.filter_queryset(queryset) - - page = self.paginate_queryset(queryset) - if page is not None: - serializer = self.get_serializer(page, many=True) - return self.get_paginated_response(serializer.data) - - serializer = self.get_serializer(queryset, many=True) - return Response(serializer.data) def destroy(self, request, *args, **kwargs): instance = self.get_object() @@ -549,23 +539,6 @@ class ExamRecordViewSet(ListModelMixin, DestroyModelMixin, RetrieveModelMixin, G ExamRecord.objects.filter(create_time__lte=days7_ago, is_submited=False).delete(soft=False) return Response(status=False) - @action(methods=['get'], detail=False, permission_classes=[IsAuthenticated]) - def self(self, request, pk=None): - ''' - 个人考试记录 - - 个人考试记录 - ''' - queryset = ExamRecord.objects.filter(create_by=request.user).order_by('-update_time') - queryset = self.filter_queryset(queryset) - - page = self.paginate_queryset(queryset) - if page is not None: - serializer = self.get_serializer(page, many=True) - return self.get_paginated_response(serializer.data) - - serializer = self.get_serializer(queryset, many=True) - return Response(serializer.data) @action(methods=['post'], detail=True, perms_map=[{'post': '*'}], serializer_class=ExamRecordSubmitSerializer, permission_classes = [IsAuthenticated]) @transaction.atomic From a6611245346fd928350cd41629706a3089c68cad Mon Sep 17 00:00:00 2001 From: zty Date: Fri, 31 May 2024 16:46:58 +0800 Subject: [PATCH 04/38] =?UTF-8?q?add:=20=E5=A2=9E=E5=8A=A0clone=20paper=20?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/apps/exam/views.py | 30 ++++++++++++++++++++++++++- server/server/settings_dev.py | 38 +++++++++++++++++------------------ 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/server/apps/exam/views.py b/server/apps/exam/views.py index a37e6b4..79f6ecc 100644 --- a/server/apps/exam/views.py +++ b/server/apps/exam/views.py @@ -270,6 +270,35 @@ class PaperViewSet(ModelViewSet): PaperQuestion.objects.filter(paper=paper).delete() PaperQuestion.objects.bulk_create(q_list) return Response() + + + @action(methods=['put'], detail=True, url_path='clone', url_name='clone_paper', + perms_map=[{'put':'clone_paper'}]) + def clone(self, request, pk=None): + ''' + 克隆试卷 + ''' + paper = self.get_object() + obj = Paper() + obj.name = '克隆卷-'+paper.name + obj.workscope = paper.workscope + obj.limit = paper.limit + obj.total_score = paper.total_score + obj.pass_score = paper.pass_score + obj.danxuan_count = paper.danxuan_count + obj.danxuan_score = paper.danxuan_score + obj.duoxuan_count = paper.duoxuan_count + obj.duoxuan_score = paper.duoxuan_score + obj.panduan_count = paper.panduan_count + obj.panduan_score = paper.panduan_score + obj.save() + for i in PaperQuestion.objects.filter(paper=paper): + o = PaperQuestion() + o.paper = obj + o.question = i.question + o.total_score = i.total_score + o.save() + return Response(status=200) @action(methods=['post'], detail=False, perms_map={'post': 'question'}, serializer_class=Serializer) def upload_paper(self, request): @@ -277,7 +306,6 @@ class PaperViewSet(ModelViewSet): question_type = request.data.get('question_type') excel_path = settings.BASE_DIR + "/media/default/question.xlsx" doc_path = settings.BASE_DIR + doc_path - # excel_path = "C:\code\data\question.xlsx" timenow = timezone.now().strftime('%Y%m%d%H%M%S') question_excel_name = "question_excel_"+timenow question_excel = os.path.join(os.path.dirname(excel_path), question_excel_name) diff --git a/server/server/settings_dev.py b/server/server/settings_dev.py index 3065e84..2d5ce36 100644 --- a/server/server/settings_dev.py +++ b/server/server/settings_dev.py @@ -1,14 +1,14 @@ from .settings import * DEBUG = True DATABASES = { - # 'default': { - # 'ENGINE': 'django.db.backends.postgresql', - # 'NAME': 'cma', - # 'USER': 'postgres', - # 'PASSWORD': 'zcDsj2021', - # 'HOST': '49.232.14.174', - # 'PORT': '5432', - # }, + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'cma', + 'USER': 'postgres', + 'PASSWORD': 'zcDsj2021', + 'HOST': '49.232.14.174', + 'PORT': '5432', + }, # 'default': { # 'ENGINE': 'django.db.backends.postgresql', # 'NAME': 'cma', @@ -18,16 +18,14 @@ DATABASES = { # # 'HOST': '1.203.161.102', # 'PORT': '5432', # } - 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': 'cma', - 'USER': 'cma', - 'PASSWORD': 'cma123', - 'HOST': '172.16.80.102', - # 'HOST': '127.0.0.1', - # 'HOST':'1.203.161.101', - 'PORT': '5432', - } - - + # 'default': { + # 'ENGINE': 'django.db.backends.postgresql', + # 'NAME': 'cma', + # 'USER': 'cma', + # 'PASSWORD': 'cma123', + # 'HOST': '172.16.80.102', + # # 'HOST': '127.0.0.1', + # # 'HOST':'1.203.161.101', + # 'PORT': '5432', + # } } From 7449f98cb659e386463eb2f8352b67594606dc2c Mon Sep 17 00:00:00 2001 From: zty Date: Mon, 3 Jun 2024 09:51:05 +0800 Subject: [PATCH 05/38] fix add user of exam --- client/dist/index.html | 2 +- client/src/views/exam/examRecord.vue | 8 ++-- client/src/views/exam/testPaper.vue | 4 +- client/src/views/system/userExam.vue | 71 ++++++++++++++++++++++++++-- 4 files changed, 73 insertions(+), 12 deletions(-) diff --git a/client/dist/index.html b/client/dist/index.html index b61a847..4b77dbf 100644 --- a/client/dist/index.html +++ b/client/dist/index.html @@ -1 +1 @@ -vue Admin Template
\ No newline at end of file +vue Admin Template
\ No newline at end of file diff --git a/client/src/views/exam/examRecord.vue b/client/src/views/exam/examRecord.vue index 2f1f641..8c90f05 100644 --- a/client/src/views/exam/examRecord.vue +++ b/client/src/views/exam/examRecord.vue @@ -84,18 +84,18 @@