From 01be8f6c3038cff17bacefae01cf5f43b9b87434 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 17 Mar 2020 20:02:18 +0800 Subject: [PATCH] testrule --- test_client/src/api/examtest.js | 29 +++ test_client/src/router/index.js | 50 +++-- test_client/src/views/examtest/rule.vue | 113 +++++++++++ test_client/src/views/examtest/rulecreate.vue | 138 +++++++++++++ test_client/src/views/examtest/ruleedit.vue | 187 ++++++++++++++++++ test_server/examtest/__init__.py | 0 test_server/examtest/admin.py | 3 + test_server/examtest/apps.py | 5 + .../examtest/migrations/0001_initial.py | 34 ++++ test_server/examtest/migrations/__init__.py | 0 test_server/examtest/models.py | 11 ++ test_server/examtest/serializers.py | 19 ++ test_server/examtest/tests.py | 3 + test_server/examtest/urls.py | 11 ++ test_server/examtest/views.py | 33 ++++ .../migrations/0006_auto_20200317_1445.py | 24 +++ test_server/question/views.py | 3 +- test_server/requirements.txt | Bin 2584 -> 918 bytes test_server/server/settings.py | 7 +- test_server/server/urls.py | 1 + 20 files changed, 645 insertions(+), 26 deletions(-) create mode 100644 test_client/src/api/examtest.js create mode 100644 test_client/src/views/examtest/rule.vue create mode 100644 test_client/src/views/examtest/rulecreate.vue create mode 100644 test_client/src/views/examtest/ruleedit.vue create mode 100644 test_server/examtest/__init__.py create mode 100644 test_server/examtest/admin.py create mode 100644 test_server/examtest/apps.py create mode 100644 test_server/examtest/migrations/0001_initial.py create mode 100644 test_server/examtest/migrations/__init__.py create mode 100644 test_server/examtest/models.py create mode 100644 test_server/examtest/serializers.py create mode 100644 test_server/examtest/tests.py create mode 100644 test_server/examtest/urls.py create mode 100644 test_server/examtest/views.py create mode 100644 test_server/question/migrations/0006_auto_20200317_1445.py diff --git a/test_client/src/api/examtest.js b/test_client/src/api/examtest.js new file mode 100644 index 0000000..be2601a --- /dev/null +++ b/test_client/src/api/examtest.js @@ -0,0 +1,29 @@ +import request from '@/utils/request' + +export function getTestRuleAll() { + return request({ + url: '/examtest/testrule/', + method: 'get', + }) +} + +export function createTestRule(data) { + return request({ + url: '/examtest/testrule/', + method: 'post', + data + }) +} +export function updateTestRule(id, data) { + return request({ + url: `/examtest/testrule/${id}/`, + method: 'put', + data + }) +} +export function deleteTestRule(id) { + return request({ + url: `/examtest/testrule/${id}/`, + method: 'delete', + }) +} diff --git a/test_client/src/router/index.js b/test_client/src/router/index.js index c751e13..c2dd927 100644 --- a/test_client/src/router/index.js +++ b/test_client/src/router/index.js @@ -51,9 +51,10 @@ export const constantRoutes = [ path: 'dashboard', name: 'Dashboard', component: () => import('@/views/dashboard/index'), - meta: { title: '首页', icon: 'dashboard' } + meta: { title: '首页', icon: '' } }] - } + }, + ] @@ -67,19 +68,19 @@ export const asyncRoutes = [ component: Layout, redirect: '/crm/', name: 'Crm', - meta: { title: '客户管理', icon: 'example', perms: ['custom_manage'] }, + meta: { title: '客户管理', icon: '', perms: ['custom_manage'] }, children: [ { path: 'company', name: 'Company', component: () => import('@/views/crm/company.vue'), - meta: { title: '客户企业', icon: 'user', perms: ['company_manage'] } + meta: { title: '客户企业', icon: '', perms: ['company_manage'] } }, { path: 'consumer', name: 'Consumer', component: () => import('@/views/crm/consumer.vue'), - meta: { title: '学员列表', icon: 'user', perms: ['consumer_list'] } + meta: { title: '学员列表', icon: '', perms: ['consumer_list'] } }, ] }, @@ -88,19 +89,26 @@ export const asyncRoutes = [ component: Layout, redirect: '/sjmanage/', name: 'Sjmanage', - meta: { title: '试卷管理', icon: 'example'}, + meta: { title: '试卷管理', icon: ''}, children: [ { path: 'testrule', - name: 'testrule', - component: () => import('@/views/question/questioncat.vue'), - meta: { title: '模考规则', icon: 'user', perms: ['questioncat_manage'] } + name: 'TestRule', + component: () => import('@/views/examtest/rule.vue'), + meta: { title: '模考规则', icon: '', perms: ['testrule_manage'] }, }, { path: 'testpaper', name: 'testpaper', component: () => import('@/views/question/question.vue'), - meta: { title: '押题试卷', icon: 'user', perms: ['question_manage'] } + meta: { title: '押题试卷', icon: '', perms: ['question_manage'] } + }, + { + path: 'testrule/create', + name: 'CreateRule', + component: () => import('@/views/examtest/rulecreate.vue'), + meta: { title: '新建模考规则', noCache: true, icon: '', perms: ['testrule_add']}, + hidden: true }, ] }, @@ -109,19 +117,19 @@ export const asyncRoutes = [ component: Layout, redirect: '/djmanage/', name: 'Djmanage', - meta: { title: '答卷管理', icon: 'example'}, + meta: { title: '答卷管理', icon: ''}, children: [ { path: 'testrule', name: 'testrule', component: () => import('@/views/question/questioncat.vue'), - meta: { title: '答卷列表', icon: 'user', perms: ['questioncat_manage'] } + meta: { title: '答卷列表', icon: '', perms: ['questioncat_manage'] } }, { path: 'testpaper', name: 'testpaper', component: () => import('@/views/question/question.vue'), - meta: { title: '答卷统计', icon: 'user', perms: ['question_manage'] } + meta: { title: '答卷统计', icon: '', perms: ['question_manage'] } }, ] }, @@ -130,25 +138,25 @@ export const asyncRoutes = [ component: Layout, redirect: '/Qmanage/', name: 'Qmanage', - meta: { title: '题库管理', icon: 'example'}, + meta: { title: '题库管理', icon: ''}, children: [ { path: 'subject', name: 'subject', component: () => import('@/views/question/subject.vue'), - meta: { title: '学科分类', icon: 'user', perms: ['subject_manage'] } + meta: { title: '学科分类', icon: '', perms: ['subject_manage'] } }, { path: 'questioncat', name: 'questioncat', component: () => import('@/views/question/questioncat.vue'), - meta: { title: '题库分类', icon: 'user', perms: ['questioncat_manage'] } + meta: { title: '题库分类', icon: '', perms: ['questioncat_manage'] } }, { path: 'question', name: 'question', component: () => import('@/views/question/question.vue'), - meta: { title: '题目列表', icon: 'user', perms: ['question_manage'] } + meta: { title: '题目列表', icon: '', perms: ['question_manage'] } }, ] }, @@ -157,25 +165,25 @@ export const asyncRoutes = [ component: Layout, redirect: '/system/user', name: 'System', - meta: { title: '系统管理', icon: 'example', perms: ['system_manage'] }, + meta: { title: '系统管理', icon: '', perms: ['system_manage'] }, children: [ { path: 'user', name: 'User', component: () => import('@/views/system/user.vue'), - meta: { title: '用户管理', icon: 'user', perms: ['user_manage'] } + meta: { title: '用户管理', icon: '', perms: ['user_manage'] } }, { path: 'organization', name: 'Organization', component: () => import('@/views/system/organization'), - meta: { title: '部门管理', icon: 'tree', perms: ['organization_manage'] } + meta: { title: '部门管理', icon: '', perms: ['organization_manage'] } }, { path: 'role', name: 'Role', component: () => import('@/views/system/role'), - meta: { title: '角色管理', icon: 'lock', perms: ['role_manage'] } + meta: { title: '角色管理', icon: '', perms: ['role_manage'] } } ] }, diff --git a/test_client/src/views/examtest/rule.vue b/test_client/src/views/examtest/rule.vue new file mode 100644 index 0000000..63b7c19 --- /dev/null +++ b/test_client/src/views/examtest/rule.vue @@ -0,0 +1,113 @@ + + + diff --git a/test_client/src/views/examtest/rulecreate.vue b/test_client/src/views/examtest/rulecreate.vue new file mode 100644 index 0000000..7b7ae8b --- /dev/null +++ b/test_client/src/views/examtest/rulecreate.vue @@ -0,0 +1,138 @@ + + \ No newline at end of file diff --git a/test_client/src/views/examtest/ruleedit.vue b/test_client/src/views/examtest/ruleedit.vue new file mode 100644 index 0000000..d474020 --- /dev/null +++ b/test_client/src/views/examtest/ruleedit.vue @@ -0,0 +1,187 @@ + + + diff --git a/test_server/examtest/__init__.py b/test_server/examtest/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test_server/examtest/admin.py b/test_server/examtest/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/test_server/examtest/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/test_server/examtest/apps.py b/test_server/examtest/apps.py new file mode 100644 index 0000000..36b058b --- /dev/null +++ b/test_server/examtest/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ExamtestConfig(AppConfig): + name = 'examtest' diff --git a/test_server/examtest/migrations/0001_initial.py b/test_server/examtest/migrations/0001_initial.py new file mode 100644 index 0000000..90411ed --- /dev/null +++ b/test_server/examtest/migrations/0001_initial.py @@ -0,0 +1,34 @@ +# Generated by Django 3.0.4 on 2020-03-17 07:04 + +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('question', '0006_auto_20200317_1445'), + ] + + operations = [ + migrations.CreateModel( + name='TestRule', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_delete', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('name', models.CharField(max_length=200, unique=True, verbose_name='名称')), + ('detail', django.contrib.postgres.fields.jsonb.JSONField(verbose_name='试卷结构')), + ('questioncat', models.ManyToManyField(to='question.Questioncat', verbose_name='所选题库')), + ('subject', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subject', to='question.Questioncat', verbose_name='所属学科')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/test_server/examtest/migrations/__init__.py b/test_server/examtest/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test_server/examtest/models.py b/test_server/examtest/models.py new file mode 100644 index 0000000..65e638c --- /dev/null +++ b/test_server/examtest/models.py @@ -0,0 +1,11 @@ +from django.db import models +from rbac.models import CommonModel +from django.contrib.postgres.fields import JSONField, ArrayField +from question.models import Questioncat + +# Create your models here. +class TestRule(CommonModel): + name = models.CharField(max_length=200, unique=True, verbose_name="名称") + subject = models.ForeignKey(Questioncat, blank=True, null=True, on_delete=models.CASCADE, verbose_name="所属学科", related_name="subject") + questioncat = models.ManyToManyField(Questioncat, verbose_name="所选题库") + detail = JSONField(verbose_name="试卷结构") \ No newline at end of file diff --git a/test_server/examtest/serializers.py b/test_server/examtest/serializers.py new file mode 100644 index 0000000..4223345 --- /dev/null +++ b/test_server/examtest/serializers.py @@ -0,0 +1,19 @@ +from rest_framework import serializers +from question.models import Questioncat +from .models import TestRule + + + +class TestRuleSerializer(serializers.ModelSerializer): + """ + 学科分类序列化 + """ + create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) + update_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True) + class Meta: + model = TestRule + fields = '__all__' + depth = 1 + + + diff --git a/test_server/examtest/tests.py b/test_server/examtest/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/test_server/examtest/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/test_server/examtest/urls.py b/test_server/examtest/urls.py new file mode 100644 index 0000000..6554ec3 --- /dev/null +++ b/test_server/examtest/urls.py @@ -0,0 +1,11 @@ +from django.urls import path,include +from .views import TestRuleViewSet +from rest_framework import routers + + +router = routers.DefaultRouter() +router.register('testrule', TestRuleViewSet, basename="testrule") + +urlpatterns = [ + path('', include(router.urls)), +] diff --git a/test_server/examtest/views.py b/test_server/examtest/views.py new file mode 100644 index 0000000..3f29333 --- /dev/null +++ b/test_server/examtest/views.py @@ -0,0 +1,33 @@ +from rest_framework.filters import SearchFilter, OrderingFilter +from rest_framework.permissions import IsAuthenticated +from rest_framework.views import APIView +from rest_framework.viewsets import ModelViewSet +from rest_framework.generics import GenericAPIView +from rest_framework.response import Response +from rest_framework.decorators import action +from rest_framework import status +from django_filters.rest_framework import DjangoFilterBackend +from openpyxl import Workbook, load_workbook +from rest_framework_jwt.authentication import JSONWebTokenAuthentication + +from utils.custom import CommonPagination +from rbac.permission import RbacPermission +from .models import TestRule +from .serializers import TestRuleSerializer +from server import settings +from crm.authentication import ConsumerTokenAuthentication + +# Create your views here. +class TestRuleViewSet(ModelViewSet): + """ + 模考规则:增删改查 + """ + perms_map = ( + {'*': 'admin'}, {'*': 'TestRule_all'}, {'get': 'TestRule_list'}, {'post': 'TestRule_create'}, + {'put': 'TestRule_update'}, {'delete': 'TestRule_delete'}) + pagination_class = None + queryset = TestRule.objects.filter(is_delete=0).all().order_by("id") + serializer_class = TestRuleSerializer + ordering_fields = ('id',) + ordering = ['id'] + search_fields = ('^name',) \ No newline at end of file diff --git a/test_server/question/migrations/0006_auto_20200317_1445.py b/test_server/question/migrations/0006_auto_20200317_1445.py new file mode 100644 index 0000000..1a38da7 --- /dev/null +++ b/test_server/question/migrations/0006_auto_20200317_1445.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.4 on 2020-03-17 06:45 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('question', '0005_auto_20200316_1056'), + ] + + operations = [ + migrations.AlterField( + model_name='question', + name='questioncat', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='questioncat', to='question.Questioncat', verbose_name='所属题库'), + ), + migrations.AlterField( + model_name='questioncat', + name='pid', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='questioncatpid', to='question.Questioncat', verbose_name='父'), + ), + ] diff --git a/test_server/question/views.py b/test_server/question/views.py index 4889193..33887ea 100644 --- a/test_server/question/views.py +++ b/test_server/question/views.py @@ -4,7 +4,6 @@ from rest_framework.views import APIView from rest_framework.viewsets import ModelViewSet from rest_framework.generics import GenericAPIView from rest_framework.response import Response -from rest_framework.permissions import IsAuthenticated from rest_framework.decorators import action from rest_framework import status from django_filters.rest_framework import DjangoFilterBackend @@ -26,7 +25,7 @@ class SubjectViewSet(ModelViewSet): perms_map = ( {'*': 'admin'}, {'*': 'Subject_all'}, {'get': 'Subject_list'}, {'post': 'Subject_create'}, {'put': 'Subject_update'}, {'delete': 'Subject_delete'}) - queryset = Questioncat.objects.filter(is_subject=True).all().order_by("id") + queryset = Questioncat.objects.filter(is_subject=True,is_delete=0).all().order_by("id") serializer_class = SubjectSerializer pagination_class = None ordering_fields = ('id',) diff --git a/test_server/requirements.txt b/test_server/requirements.txt index 8604b6b3bd13fdd222d980e434658860c3559f8c..2ade5dfe9d0868b2eaca911daec2e00efce0ea13 100644 GIT binary patch delta 262 zcmX|+&k6xi7{$*u#u#NGYDzRIQ>4+DNyY+8va+`l3JIZ?_wR6vZmOjQ z1Uf}>riVCU=y7(=TJjD_sWHWohaQo3a*O?s;P77gBahyiDLlGIEpqjOs8CANk(jUOqD|DQ2U(nnseDT-Wp6YYb2db=cw?=yUn9Sh>Jb5I^T*%IjA|GG z2W#~QCovIJVXlV0E9qmayltLe@IUN%7y&QNjV9K)0`o!<=3wX#m*B3Yo=S*n)!KD6 zJ#DJ}4_~WZHu7iol{kg>L*}+j2epqny$@?YDY{P2QUz0e9$$Su z)mSvY$gJ%&mxCq^hef$?5&5@5dz23|X|s=~S9Wxv=y`gP4}Hdb3!iAUl6@nqXIr+! zxzJRdp7b>Gg)6Ju%$gs3m;$qgQ|izY+BVkvJRLlS8La+`tTaxEMpFn~d51kCxT5+p z&4hQ8QB38JUdpt_ol2I%;RtfYK99RSTPo%xK2QsGp9q0;rL1V7sIP43D$jiOrs71W z5#3+Q(&XJ5_xL%Bu&pv)lnL73*$#W0V?H}pLObia1Cg08>^;c7k;gH|@}3ELKiA6o zs(z}RW2LUuv0qxu576CsQ4fH|4#WL-ra1JAAV+?1+1X) z8MaYPP83e;Mx4z1XwMisyHLsIO~;dy(X+Txrn0Y%aIm4J2hQwZZ7U0k!v50DD^5FO zh4ChPbMXO%dvf|kaVPLbes2-;W zcMjh`o-YW?9vu~Jh5Lr_y+*E~Lh