diff --git a/test_client/src/api/cms.js b/test_client/src/api/cms.js index a35be50..6eb2270 100644 --- a/test_client/src/api/cms.js +++ b/test_client/src/api/cms.js @@ -38,3 +38,30 @@ export function topArticle(id) { method: 'put', }) } + +export function getMaterialList() { + return request({ + url: '/cms/material/', + method: 'get', + }) +} +export function createMaterial(data) { + return request({ + url: '/cms/material/', + method: 'post', + data + }) +} +export function updateMaterial(id, data) { + return request({ + url: `/cms/material/${id}/`, + method: 'put', + data + }) +} +export function deleteMaterial(id) { + return request({ + url: `/cms/material/${id}/`, + method: 'delete', + }) +} \ No newline at end of file diff --git a/test_client/src/api/file.js b/test_client/src/api/file.js index dcb18fe..5fa98a0 100644 --- a/test_client/src/api/file.js +++ b/test_client/src/api/file.js @@ -1,7 +1,7 @@ import { getToken } from "@/utils/auth"; -export function uploadUrl(){ +export function upUrl(){ return process.env.VUE_APP_BASE_API + '/uploadfile/' } -export function myHeaders(){ +export function upHeaders(){ return { Authorization: "JWT " + getToken() } } diff --git a/test_client/src/components/Tinymce/index.vue b/test_client/src/components/Tinymce/index.vue index fe0daed..f351ede 100644 --- a/test_client/src/components/Tinymce/index.vue +++ b/test_client/src/components/Tinymce/index.vue @@ -12,7 +12,7 @@ import plugins from "./plugins"; import toolbar from "./toolbar"; import load from "./dynamicLoadScript"; -import { uploadUrl, myHeaders } from "@/api/file"; +import { upUrl, upHeaders } from "@/api/file"; import { getToken } from "@/utils/auth"; // why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one const tinymceCDN = @@ -171,7 +171,7 @@ export default { var file = blobInfo.blob(); //转化为易于理解的file对象 xhr = new XMLHttpRequest(); xhr.withCredentials = false; - xhr.open("POST", uploadUrl()); + xhr.open("POST", upUrl()); xhr.setRequestHeader('Authorization', 'JWT '+ getToken()); xhr.onload = function() { var json; diff --git a/test_client/src/router/index.js b/test_client/src/router/index.js index 10f9f86..2e7a76e 100644 --- a/test_client/src/router/index.js +++ b/test_client/src/router/index.js @@ -68,7 +68,7 @@ export const asyncRoutes = [ component: Layout, redirect: '/cms/', name: 'CMS', - meta: { title: '资讯文章', icon: 'peoples', perms: ['news_view'] }, + meta: { title: '资料文章', icon: 'documentation', perms: ['news_view'] }, children: [ { path: 'news', @@ -76,6 +76,12 @@ export const asyncRoutes = [ component: () => import('@/views/news/news.vue'), meta: { title: '文章列表', icon: 'documentation', perms: ['news_view'] } }, + { + path: 'materials', + name: 'MaterialList', + component: () => import('@/views/material/material.vue'), + meta: { title: '学习资料', icon: 'documentation', perms: ['material_view'] } + }, { path: 'news/create', name: 'NewsCreate', diff --git a/test_client/src/views/crm/consumer.vue b/test_client/src/views/crm/consumer.vue index 42505ec..a6c2329 100644 --- a/test_client/src/views/crm/consumer.vue +++ b/test_client/src/views/crm/consumer.vue @@ -73,10 +73,10 @@ type="primary" >下载模板 上传导入 @@ -246,7 +246,7 @@ import { getWorkScopeAll } from "@/api/examtest"; import { getCompanyList } from "@/api/crm"; import { genTree, deepClone } from "@/utils"; import checkPermission from "@/utils/permission"; -import { uploadUrl } from "@/api/file"; +import { upUrl } from "@/api/file"; import { getToken } from "@/utils/auth"; import Pagination from "@/components/Pagination"; // secondary package based on el-pagination @@ -274,10 +274,10 @@ export default { return { tableKey: 0, showCreate: false, - uploadUrl: uploadUrl(), + upUrl: upUrl(), popovervisible: false, consumer: defaultConsumer, - myHeaders: { Authorization: "JWT " + getToken() }, + upHeaders: { Authorization: "JWT " + getToken() }, consumerList: [], total: 0, listLoading: true, diff --git a/test_client/src/views/material/material.vue b/test_client/src/views/material/material.vue new file mode 100644 index 0000000..e7e6047 --- /dev/null +++ b/test_client/src/views/material/material.vue @@ -0,0 +1,246 @@ + + diff --git a/test_client/src/views/question/question.vue b/test_client/src/views/question/question.vue index 1cd61db..0a51055 100644 --- a/test_client/src/views/question/question.vue +++ b/test_client/src/views/question/question.vue @@ -54,10 +54,10 @@
下载模板 上传导入 @@ -158,7 +158,7 @@ import { import { genTree, deepClone } from "@/utils"; import checkPermission from "@/utils/permission"; import Pagination from "@/components/Pagination"; -import { uploadUrl, myHeaders } from "@/api/file"; +import { upUrl, upHeaders } from "@/api/file"; import { getToken } from "@/utils/auth"; const defaultObj = { @@ -175,8 +175,8 @@ export default { data() { return { popovervisible:false, - uploadUrl: uploadUrl(), - myHeaders: myHeaders(), + upUrl: upUrl(), + upHeaders: upHeaders(), questioncat: { id: "", name: "" diff --git a/test_client/src/views/question/questioncreate.vue b/test_client/src/views/question/questioncreate.vue index 7aa1083..75f38a5 100644 --- a/test_client/src/views/question/questioncreate.vue +++ b/test_client/src/views/question/questioncreate.vue @@ -35,8 +35,8 @@ import { createQuestion,getQuestioncatAll } from "@/api/question"; import { genTree, deepClone } from "@/utils"; -import { uploadUrl } from "@/api/file"; +import { upUrl } from "@/api/file"; import { getToken } from "@/utils/auth"; export default { data() { return { - myHeaders: { Authorization: "JWT " + getToken() }, - uploadUrl: uploadUrl(), + upHeaders: { Authorization: "JWT " + getToken() }, + upUrl: upUrl(), Form: { name: "", type:"", diff --git a/test_client/src/views/question/questionupdate.vue b/test_client/src/views/question/questionupdate.vue index c842efd..5abfdc2 100644 --- a/test_client/src/views/question/questionupdate.vue +++ b/test_client/src/views/question/questionupdate.vue @@ -36,8 +36,8 @@ import { createQuestion,getQuestioncatAll, getQuestion, getQuestioncatList, updateQuestion } from "@/api/question"; import { genTree, deepClone } from "@/utils"; -import { uploadUrl } from "@/api/file"; +import { upUrl } from "@/api/file"; import { getToken } from "@/utils/auth"; export default { data() { return { - myHeaders: { Authorization: "JWT " + getToken() }, - uploadUrl: uploadUrl(), + upHeaders: { Authorization: "JWT " + getToken() }, + upUrl: upUrl(), Form: { id:0, name: "", diff --git a/test_client/src/views/system/banner.vue b/test_client/src/views/system/banner.vue index a6ba14c..93566cd 100644 --- a/test_client/src/views/system/banner.vue +++ b/test_client/src/views/system/banner.vue @@ -67,8 +67,8 @@ @@ -213,7 +213,7 @@ import { getOrgList } from "@/api/org"; import { getRoles } from "@/api/role"; import { genTree, deepClone } from "@/utils"; import checkPermission from "@/utils/permission"; -import { uploadUrl } from "@/api/file"; +import { upUrl } from "@/api/file"; import { getToken } from "@/utils/auth"; import Pagination from "@/components/Pagination"; // secondary package based on el-pagination @@ -240,8 +240,8 @@ export default { department: null, avatar:"" }, - myHeaders: { Authorization: "JWT " + getToken() }, - uploadUrl: uploadUrl(), + upHeaders: { Authorization: "JWT " + getToken() }, + upUrl: upUrl(), userList: [], roles: [], total: 0, diff --git a/test_mini/pages/quota/quota.js b/test_mini/pages/quota/quota.js index 8af6002..f39e227 100644 --- a/test_mini/pages/quota/quota.js +++ b/test_mini/pages/quota/quota.js @@ -1,4 +1,5 @@ // pages/quota/quota.js +const api = require("../../utils/request.js"); Page({ /** @@ -12,7 +13,7 @@ Page({ * 生命周期函数--监听页面加载 */ onLoad: function (options) { - + this.getList() }, /** @@ -47,7 +48,8 @@ Page({ * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { - + this.getList() + wx.stopPullDownRefresh() }, /** @@ -62,5 +64,22 @@ Page({ */ onShareAppMessage: function () { + }, + Baoming: function () { + wx.navigateToMiniProgram({ + appId: 'wxdcf5bbfb50dbbac8', + path: '', + success(res) { + // 打开其他小程序成功同步触发 + // wx.showToast({ + // title: '跳转成功' + // }) + } + }) + }, + getList:function(){ + api.request('/analyse/quota/', 'GET').then(res => { + this.setData(res.data) + }) } }) \ No newline at end of file diff --git a/test_mini/pages/quota/quota.json b/test_mini/pages/quota/quota.json index 8835af0..2a7b263 100644 --- a/test_mini/pages/quota/quota.json +++ b/test_mini/pages/quota/quota.json @@ -1,3 +1,5 @@ { - "usingComponents": {} + "usingComponents": {}, + "enablePullDownRefresh": true, + "onReachBottomDistance": 50 } \ No newline at end of file diff --git a/test_mini/pages/quota/quota.wxml b/test_mini/pages/quota/quota.wxml index 885d0cf..b296531 100644 --- a/test_mini/pages/quota/quota.wxml +++ b/test_mini/pages/quota/quota.wxml @@ -1,2 +1,35 @@ -pages/quota/quota.wxml + + + 更新时间:{{update_time}} + 前往正式报名 + + + + + {{item.cityName}} {{item.examDate}} + + 考试时间: + {{item.examTime}} + - + 截止报名: + {{item.endSignDate}} + + + 联系电话:{{item.linkContact}} + + + {{item.planName}} + + + + + 余{{item.validNum}}名 + + + 共{{item.pNum}}名 + + + + + \ No newline at end of file diff --git a/test_mini/pages/quota/quota.wxss b/test_mini/pages/quota/quota.wxss index 9afd70a..59891b9 100644 --- a/test_mini/pages/quota/quota.wxss +++ b/test_mini/pages/quota/quota.wxss @@ -1 +1,6 @@ -/* pages/quota/quota.wxss */ \ No newline at end of file +/* pages/quota/quota.wxss */ +.head{ + color:#fff; + background-color: cornflowerblue; + text-align: center; +} \ No newline at end of file diff --git a/test_server/cms/migrations/0005_material.py b/test_server/cms/migrations/0005_material.py new file mode 100644 index 0000000..b96b45a --- /dev/null +++ b/test_server/cms/migrations/0005_material.py @@ -0,0 +1,30 @@ +# Generated by Django 3.0.5 on 2020-06-26 09:00 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('cms', '0004_auto_20200429_1205'), + ] + + operations = [ + migrations.CreateModel( + name='Material', + 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, verbose_name='标题')), + ('description', models.TextField(blank=True, null=True, verbose_name='描述')), + ('path', models.CharField(max_length=1000, verbose_name='文件地址')), + ('read_count', models.IntegerField(default=0, verbose_name='阅读量')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/test_server/cms/migrations/0006_auto_20200626_1741.py b/test_server/cms/migrations/0006_auto_20200626_1741.py new file mode 100644 index 0000000..024f3b4 --- /dev/null +++ b/test_server/cms/migrations/0006_auto_20200626_1741.py @@ -0,0 +1,23 @@ +# Generated by Django 3.0.5 on 2020-06-26 09:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cms', '0005_material'), + ] + + operations = [ + migrations.RenameField( + model_name='material', + old_name='read_count', + new_name='down_count', + ), + migrations.AlterField( + model_name='material', + name='name', + field=models.CharField(max_length=200, unique=True, verbose_name='标题'), + ), + ] diff --git a/test_server/cms/models.py b/test_server/cms/models.py index 46d65bf..98cc1a6 100644 --- a/test_server/cms/models.py +++ b/test_server/cms/models.py @@ -25,5 +25,7 @@ class Material(CommonModel): """ 学习资料 """ - name = models.CharField(max_length=200, verbose_name='标题') - description = models.TextField('描述') \ No newline at end of file + name = models.CharField(max_length=200, verbose_name='标题', unique=True) + description = models.TextField('描述', null=True, blank=True) + path = models.CharField(max_length=1000, verbose_name='文件地址') + down_count = models.IntegerField('阅读量', default=0) diff --git a/test_server/cms/serializers.py b/test_server/cms/serializers.py index 4165e3f..9f48095 100644 --- a/test_server/cms/serializers.py +++ b/test_server/cms/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from .models import Article +from .models import Article, Material class ArticelSerializer(serializers.ModelSerializer): @@ -21,3 +21,10 @@ class ArticelListSerializer(serializers.ModelSerializer): class Meta: model = Article exclude = ('content',) + +class MaterialSerializer(serializers.ModelSerializer): + class Meta: + model = Material + fields = '__all__' + + diff --git a/test_server/cms/urls.py b/test_server/cms/urls.py index bcf8fae..c1b7c24 100644 --- a/test_server/cms/urls.py +++ b/test_server/cms/urls.py @@ -1,10 +1,11 @@ from django.urls import path,include -from .views import ArticleViewSet +from .views import ArticleViewSet, MaterialViewSet from rest_framework import routers router = routers.DefaultRouter() router.register('article', ArticleViewSet, basename="article") +router.register('material', MaterialViewSet, basename="material") urlpatterns = [ path('', include(router.urls)), diff --git a/test_server/cms/views.py b/test_server/cms/views.py index 6d30954..f88292c 100644 --- a/test_server/cms/views.py +++ b/test_server/cms/views.py @@ -21,8 +21,8 @@ from rest_framework_jwt.serializers import (jwt_encode_handler, from rest_framework_jwt.settings import api_settings # Create your views here. -from .models import Article -from .serializers import ArticelSerializer, ArticelListSerializer +from .models import Article, Material +from .serializers import ArticelSerializer, ArticelListSerializer, MaterialSerializer from utils.custom import CommonPagination class ArticleViewSet(ModelViewSet): """ @@ -35,8 +35,8 @@ class ArticleViewSet(ModelViewSet): serializer_class = ArticelSerializer pagination_class = CommonPagination filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter] - search_fields = ('^title','^content') - ordering_fields = ('title','update_time') + search_fields = ['title','content'] + ordering_fields = ['title','update_time'] ordering = ['-is_top', '-update_time'] def get_serializer_class(self): @@ -53,4 +53,29 @@ class ArticleViewSet(ModelViewSet): instance = self.get_object() instance.is_top = False if instance.is_top else True instance.save() + return Response(status=status.HTTP_200_OK) + +class MaterialViewSet(ModelViewSet): + """ + 资料:增删改查 + """ + perms_map = [ + {'get': 'material_list'}, {'post': 'material_create'}, + {'put': 'material_update'}, {'delete': 'material_delete'}] + queryset = Material.objects.filter(is_delete=0) + serializer_class = MaterialSerializer + pagination_class = CommonPagination + filter_backends = [DjangoFilterBackend,SearchFilter, OrderingFilter] + search_fields = ['name','description'] + ordering_fields = ['update_time', 'down_count'] + ordering = ['-update_time'] + + @action(methods=['get'], detail=True, url_name='down_material', perms_map=[{'*':'down_material'}]) + def down(self, request, *args, **kwargs): + ''' + 下载资料 + ''' + instance = self.get_object() + instance.down_count = instance.down_count + 1 + instance.save() return Response(status=status.HTTP_200_OK) \ No newline at end of file diff --git a/test_server/server/settings.py b/test_server/server/settings.py index 2acf210..166c269 100644 --- a/test_server/server/settings.py +++ b/test_server/server/settings.py @@ -155,6 +155,8 @@ REST_FRAMEWORK = { 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema', 'UNAUTHENTICATED_USER': None, 'UNAUTHENTICATED_TOKEN': None, + 'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S', + 'DATE_FORMAT': '%Y-%m-%d', } JWT_AUTH = {