加入练习中心客户端和管理端的框架
This commit is contained in:
@@ -45,6 +45,7 @@ INSTALLED_APPS = [
|
||||
'rest_framework',
|
||||
'django_filters',
|
||||
'import_export',
|
||||
'study',
|
||||
'user',
|
||||
'exam',
|
||||
'question',
|
||||
|
||||
@@ -24,7 +24,7 @@ from question.views import ChoiceListViewSet, FillListViewSet, JudgeListViewSet,
|
||||
from record.views import ChoiceRecordListViewSet, FillRecordListViewSet, JudgeRecordListViewSet, \
|
||||
ProgramRecordListViewSet
|
||||
from user.views import RegisterViewSet, StudentViewSet, UpdatePwdApi, ClazzListViewSet
|
||||
|
||||
from study.views import StudyListViewSet,get_content
|
||||
router = DefaultRouter()
|
||||
|
||||
# 配置exams的url
|
||||
@@ -42,6 +42,7 @@ router.register(r'records/choices', ChoiceRecordListViewSet)
|
||||
router.register(r'records/fills', FillRecordListViewSet)
|
||||
router.register(r'records/judges', JudgeRecordListViewSet)
|
||||
router.register(r'records/programs', ProgramRecordListViewSet)
|
||||
router.register(r'studies', StudyListViewSet)
|
||||
|
||||
urlpatterns = [
|
||||
path('xadmin/', xadmin.site.urls),
|
||||
@@ -50,5 +51,6 @@ urlpatterns = [
|
||||
path('jwt-auth/', obtain_jwt_token),
|
||||
path('check-program/', CheckProgramApi.as_view()),
|
||||
path('update-pwd/', UpdatePwdApi.as_view()),
|
||||
path("content/", get_content),
|
||||
re_path('^', include(router.urls))
|
||||
]
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
default_app_config = 'study.apps.StudyConfig'
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@@ -0,0 +1,15 @@
|
||||
import xadmin
|
||||
|
||||
from study.models import Study
|
||||
from study.resource import StudyResource
|
||||
|
||||
class StudyAdmin(object):
|
||||
list_display = ['id', 'name', 'desc', 'relate_points', 'relate_questions', 'study_times', 'add_time']
|
||||
search_fields = ['name', 'desc', 'relate_points', 'relate_questions']
|
||||
list_filter = ['name', 'desc', 'relate_points', 'relate_questions', 'study_times', 'add_time']
|
||||
import_export_args = {'import_resource_class': StudyResource, 'export_resource_class': StudyResource}
|
||||
|
||||
|
||||
|
||||
|
||||
xadmin.site.register(Study, StudyAdmin)
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class StudyConfig(AppConfig):
|
||||
name = 'study'
|
||||
verbose_name = '学习中心管理'
|
||||
@@ -0,0 +1,50 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"label": "一级 1",
|
||||
"children": [
|
||||
{
|
||||
"id": 4,
|
||||
"label": "二级 1-1",
|
||||
"children": [
|
||||
{
|
||||
"id": 9,
|
||||
"label": "三级 1-1-1"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"label": "三级 1-1-2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"label": "一级 2",
|
||||
"children": [
|
||||
{
|
||||
"id": 5,
|
||||
"label": "二级 2-1"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"label": "二级 2-2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"label": "一级 3",
|
||||
"children": [
|
||||
{
|
||||
"id": 7,
|
||||
"label": "二级 3-1"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"label": "二级 3-2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
# Create your models here.
|
||||
class Study(models.Model):
|
||||
"""学习资料"""
|
||||
name = models.CharField("学习资料目录名称", max_length=100)
|
||||
desc = models.TextField("学习内容描述", null=True, blank=True)
|
||||
relate_points = models.TextField("相关知识点", null=True, blank=True)
|
||||
relate_questions = models.TextField("相关题目", null=True, blank=True)
|
||||
study_times = models.IntegerField("学习次数", default=0)
|
||||
add_time = models.DateTimeField("添加时间", auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ['id']
|
||||
verbose_name = '资料库'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@@ -0,0 +1,8 @@
|
||||
from import_export import resources
|
||||
|
||||
from study.models import Study
|
||||
|
||||
class StudyResource(resources.ModelResource):
|
||||
class Meta:
|
||||
model = Study
|
||||
fields = ('id', 'name', 'desc', 'relate_points', 'relate_questions', 'study_times', 'add_time')
|
||||
@@ -0,0 +1,7 @@
|
||||
from rest_framework import serializers
|
||||
from study.models import Study
|
||||
|
||||
class StudySerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Study
|
||||
fields = '__all__'
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,42 @@
|
||||
import subprocess
|
||||
import json
|
||||
import os
|
||||
from django.http import JsonResponse
|
||||
from rest_framework import mixins, viewsets
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from study.models import Study
|
||||
from study.serializers import StudySerializer
|
||||
|
||||
|
||||
# Create your views here.
|
||||
|
||||
|
||||
class StudyListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
|
||||
"""选择题列表页"""
|
||||
# 这里要定义一个默认的排序,否则会报错
|
||||
queryset = Study.objects.all().order_by('id')[:0]
|
||||
# 序列化
|
||||
serializer_class = StudySerializer
|
||||
|
||||
# 重写queryset
|
||||
def get_queryset(self):
|
||||
# 题目数量
|
||||
choice_number = int(self.request.query_params.get("choice_number", 0))
|
||||
level = int(self.request.query_params.get("level", 1))
|
||||
content = self.request.query_params.get("content", 0)
|
||||
if choice_number:
|
||||
self.queryset = Study.objects.all().filter(level=level).order_by('?')[:choice_number]
|
||||
return self.queryset
|
||||
|
||||
|
||||
def get_content(request):
|
||||
with open("./study/content.json",encoding="utf-8") as f:
|
||||
content = json.load(f)
|
||||
res = {
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": content
|
||||
}
|
||||
return JsonResponse(res)
|
||||
@@ -7,6 +7,7 @@
|
||||
<el-menu :default-active="activeIndex" class="el-menu-title" mode="horizontal" @select="handleSelect"
|
||||
background-color="#ffffff" text-color="#85baef" active-text-color="#1884f2" :router="true">
|
||||
<el-menu-item index="/exam">考试中心</el-menu-item>
|
||||
<el-menu-item index="/study">练习中心</el-menu-item>
|
||||
<el-menu-item index="/practice">模拟练习</el-menu-item>
|
||||
<el-menu-item index="/grade">查询成绩</el-menu-item>
|
||||
<el-menu-item index="/mistake" disabled>错题本</a></el-menu-item>
|
||||
|
||||
@@ -16,6 +16,14 @@ const routes = [{
|
||||
title: '考试中心'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'study',
|
||||
component: () => import('../views/Study.vue'),
|
||||
name: 'study',
|
||||
meta: {
|
||||
title: '学习中心'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'practice',
|
||||
name: 'Practice',
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
|
||||
<div>
|
||||
<!-- 左边的树状结构-->
|
||||
<div class="custom-tree-container">
|
||||
<div class="block">
|
||||
<p>章节目录</p>
|
||||
<el-tree
|
||||
:data="data"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
default-expand-all
|
||||
:expand-on-click-node="false"
|
||||
:render-content="renderContent">
|
||||
</el-tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 右边的对应内容-->
|
||||
<div class="content">
|
||||
<textarea v-model="content" class="content-textarea"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let id = 1000;
|
||||
|
||||
export default {
|
||||
data() {
|
||||
const data = [{
|
||||
id: 1,
|
||||
label: '一级 1',
|
||||
children: [{
|
||||
id: 4,
|
||||
label: '二级 1-1',
|
||||
children: [{
|
||||
id: 9,
|
||||
label: '三级 1-1-1'
|
||||
}, {
|
||||
id: 10,
|
||||
label: '三级 1-1-2'
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
id: 2,
|
||||
label: '一级 2',
|
||||
children: [{
|
||||
id: 5,
|
||||
label: '二级 2-1'
|
||||
}, {
|
||||
id: 6,
|
||||
label: '二级 2-2'
|
||||
}]
|
||||
}, {
|
||||
id: 3,
|
||||
label: '一级 3',
|
||||
children: [{
|
||||
id: 7,
|
||||
label: '二级 3-1'
|
||||
}, {
|
||||
id: 8,
|
||||
label: '二级 3-2'
|
||||
}]
|
||||
}];
|
||||
return {
|
||||
data: JSON.parse(JSON.stringify(data)),
|
||||
data: JSON.parse(JSON.stringify(data))
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
append(data) {
|
||||
const newChild = {id: id++, label: 'testtest', children: []};
|
||||
if (!data.children) {
|
||||
this.$set(data, 'children', []);
|
||||
}
|
||||
data.children.push(newChild);
|
||||
},
|
||||
|
||||
remove(node, data) {
|
||||
const parent = node.parent;
|
||||
const children = parent.data.children || parent.data;
|
||||
const index = children.findIndex(d => d.id === data.id);
|
||||
children.splice(index, 1);
|
||||
},
|
||||
|
||||
renderContent(h, {node, data, store}) {
|
||||
return (
|
||||
<span class="custom-tree-node">
|
||||
<span>{node.label}</span>
|
||||
<span>
|
||||
<el-button size="mini" type="text" on-click={() => this.append(data)}>Append</el-button>
|
||||
<el-button size="mini" type="text" on-click={() => this.remove(node, data)}>Delete</el-button>
|
||||
</span>
|
||||
</span>);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.custom-tree-node {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.block {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: black;
|
||||
width: 70%;
|
||||
float: right;
|
||||
margin-right: 5%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user