This commit is contained in:
caoqianming 2020-04-26 17:44:10 +08:00
parent 875069ac9f
commit 426c2fdae1
13 changed files with 200 additions and 33 deletions

View File

@ -6,3 +6,4 @@ export function getBasicCount() {
method: 'get',
})
}

View File

@ -61,4 +61,11 @@ export function importConsumer(data) {
method: 'post',
data
})
}
export function exportConsumer(query) {
return request({
url: '/crm/consumer/export',
method: 'get',
params: query
})
}

View File

@ -117,4 +117,11 @@ export function deletePaper(id) {
url: `/examtest/paper/${id}/`,
method: 'delete',
})
}
export function exportTest(query) {
return request({
url: '/examtest/examtest/export',
method: 'get',
params: query
})
}

View File

@ -7,7 +7,7 @@ import { getToken } from '@/utils/auth'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 10000, // request timeout
timeout: 30000, // request timeout
})
// request interceptor

View File

@ -31,12 +31,23 @@
:value="item.value"
/>
</el-select>
<el-date-picker
v-model="value"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:picker-options="pickerOptions">
</el-date-picker>
<el-button
class="filter-item"
type="primary"
icon="el-icon-refresh-left"
@click="resetFilter"
>刷新重置</el-button>
<el-button type="primary" icon="el-icon-download" @click="exportTest">导出Excel</el-button>
<div style="margin-top:10px">
</div>
</div>
@ -67,7 +78,7 @@
<template slot-scope="scope">{{ scope.row.score }}</template>
</el-table-column>
<el-table-column align="left" label="耗时(秒)">
<template slot-scope="scope">{{ scope.row.took }}</template>
<template slot-scope="scope">{{ scope.row.took_format }}</template>
</el-table-column>
<el-table-column align="left" label="答题时间">
<template slot-scope="scope">{{ scope.row.start_time }}</template>
@ -94,7 +105,7 @@
</template>
<script>
import { getExamTestlist } from "@/api/examtest";
import { getExamTestlist, exportTest } from "@/api/examtest";
import checkPermission from "@/utils/permission";
import Pagination from "@/components/Pagination";
@ -121,6 +132,42 @@ export default {
{ key: true, label: "通过", value: true },
{ key: false, label: "未通过", value: false},
],
pickerOptions: {
shortcuts: [{
text: '最近一天',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近一周',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近一个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近三个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
}
}]
},
value: '',
};
},
computed: {},
@ -152,6 +199,13 @@ export default {
// this.dialogVisible = true
// this.question = scope.row
},
exportTest() {
const loading = this.$loading();
exportTest(this.listQuery).then(response => {
loading.close()
window.open(response.data.path, "_blank");
});
}
}
};
</script>

View File

@ -32,7 +32,7 @@
/>
</el-select> -->
<el-input
v-model="search"
v-model="listQuery.search"
placeholder="姓名或手机号"
style="width: 200px;"
class="filter-item"
@ -68,8 +68,9 @@
<el-button size="small" type="primary" @click="popovervisible = false">上传导入</el-button>
</el-upload>
</div>
<el-button slot="reference">Excel导入</el-button>
<el-button slot="reference" icon="el-icon-upload2">Excel导入</el-button>
</el-popover>
<el-button type="primary" icon="el-icon-download" @click="exportConsumer">导出Excel</el-button>
</div>
<el-table
:data="consumerList"
@ -210,7 +211,8 @@ import {
createConsumer,
deleteConsumer,
updateConsumer,
importConsumer
importConsumer,
exportConsumer
} from "@/api/crm";
import { getSubjectAll } from "@/api/question"
import { getWorkScopeAll } from "@/api/examtest"
@ -231,7 +233,8 @@ const defaultConsumer = {
};
const listQuery = {
page: 1,
limit: 20
limit: 20,
search:''
};
export default {
components: { Pagination },
@ -251,9 +254,9 @@ export default {
listLoading: true,
listQuery: {
page: 1,
limit: 20
limit: 20,
search:''
},
search: "",
enabledOptions: [
{ key: "true", display_name: "已缴" },
{ key: "false", display_name: "未缴" }
@ -341,7 +344,8 @@ export default {
resetFilter() {
this.listQuery = {
page: 1,
limit: 20
limit: 20,
search: ''
};
this.getList();
},
@ -350,7 +354,7 @@ export default {
this.getList();
},
handleSearch() {
this.getList({ search: this.search });
this.getList(this.listQuery);
},
handleAddUser() {
this.consumer = Object.assign({}, defaultConsumer);
@ -430,6 +434,13 @@ export default {
return false;
}
});
},
exportConsumer() {
const loading = this.$loading();
exportConsumer(this.listQuery).then(response => {
loading.close()
window.open(response.data.path, "_blank");
});
}
}
};

View File

@ -0,0 +1,26 @@
from openpyxl.workbook import Workbook
from django.conf import settings
from datetime import datetime
from openpyxl.styles import Font, Fill
BASE_DIR = settings.BASE_DIR
def export_consumer(users):
'''
params: serializer users
return: xlsx path
'''
wb = Workbook()
ws1 = wb.active
ws1.title = '用户表'
ws1.append(['姓名','手机号', '单位', '微信昵称', '工作类别', '创建日期'])
row = ws1.row_dimensions[1]
row.font = Font(bold=True)
for i in users:
ws1.append([i['name'], i['username'], i['company_name'], i['nickname'], i['workscope_name'], i['create_time']])
filename = 'users' + datetime.now().strftime("%Y%m%d%H%M%S") +'.xlsx'
path = '/media/export/' + filename
wb.save((BASE_DIR + path).replace('\\', '/'))
return path

View File

@ -5,6 +5,7 @@ from calendar import timegm
from datetime import datetime
import requests
from django.db.models import Q
from django_filters.rest_framework import DjangoFilterBackend
from openpyxl import Workbook, load_workbook
from rest_framework import status
@ -15,7 +16,8 @@ from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler
from rest_framework_jwt.serializers import (jwt_encode_handler,
jwt_payload_handler)
from rest_framework_jwt.settings import api_settings
from crm.zhenzismsclient import ZhenziSmsClient
@ -25,6 +27,7 @@ from question.serializers import QuestionSerializer
from server import settings
from utils.custom import CommonPagination
from .exports import export_consumer
from .models import Company, Consumer, PaySubject, SendCode
from .serializers import CompanySerializer, ConsumerSerializer
@ -229,10 +232,13 @@ class ConsumerViewSet(ModelViewSet):
return Response(status=status.HTTP_200_OK)
@action(methods=['get'], detail=False,
url_path='export', url_name='export_consumer')
url_path='export', url_name='export_consumer', perms_map=[{'*':'export_consumer'}])
def export(self, request):
queryset = self.filter_queryset(self.queryset)
print(queryset)
queryset = ConsumerSerializer.setup_eager_loading(queryset) # 性能优化
serializer = ConsumerSerializer(instance=queryset, many=True)
path = export_consumer(serializer.data)
return Response({'path': path})
class ConsumerMPLoginView(APIView):
"""

View File

@ -0,0 +1,26 @@
from openpyxl.workbook import Workbook
from django.conf import settings
from datetime import datetime
from openpyxl.styles import Font, Fill
BASE_DIR = settings.BASE_DIR
def export_test(tests):
'''
params: serializer tests
return: xlsx path
'''
wb = Workbook()
ws1 = wb.active
ws1.title = '用户表'
ws1.append(['类型','用户姓名', '用户单位', '工作类别', '押题卷', '得分', '耗时', '答题时间'])
row = ws1.row_dimensions[1]
row.font = Font(bold=True)
for i in tests:
ws1.append([i['type'], i['consumer_name'], i['consumer_company_name'], i['workscope_name'], i['paper_name'], i['score'], i['took_format'], i['start_time']])
filename = 'tests' + datetime.now().strftime("%Y%m%d%H%M%S") +'.xlsx'
path = '/media/export/' + filename
wb.save((BASE_DIR + path).replace('\\', '/'))
return path

View File

@ -62,6 +62,8 @@ class ExamTestListSerializer(serializers.ModelSerializer):
workscope_name = serializers.StringRelatedField(source='workscope', read_only=True)
paper_name = serializers.StringRelatedField(source='paper', read_only=True)
consumer_name = serializers.SerializerMethodField()
took_format = serializers.SerializerMethodField()
consumer_company_name = serializers.SerializerMethodField()
class Meta:
model = ExamTest
exclude = ('detail',)
@ -69,6 +71,21 @@ class ExamTestListSerializer(serializers.ModelSerializer):
def get_consumer_name(self, obj):
return obj.consumer.name
def get_took_format(self, obj):
m, s = divmod(obj.took, 60)
h, m = divmod(m, 60)
return "%02d:%02d:%02d" % (h, m, s)
def get_consumer_company_name(self, obj):
if obj.consumer.company:
return obj.consumer.company.name
@staticmethod
def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.select_related('consumer','paper', 'workscope')
return queryset
class AnswerDetailSerializer(serializers.ModelSerializer):
class Meta:
model = AnswerDetail

View File

@ -18,6 +18,7 @@ from question.serializers import QuestionSerializer
from server import settings
from utils.custom import CommonPagination
from .exports import export_test
from .models import AnswerDetail, Banner, ExamTest
from .models_paper import Paper, PaperQuestions, TestRule, WorkScope
from .serializers import (
@ -258,8 +259,15 @@ class ExamTestViewSet(ModelViewSet):
return Response({'error':'答题记录不存在'})
else:
return Response(serializer.errors)
@action(methods=['get'], detail=False,
url_path='export', url_name='export_test', perms_map=[{'*':'export_test'}])
def export(self, request):
queryset = self.filter_queryset(self.queryset)
queryset = ExamTestListSerializer.setup_eager_loading(queryset) # 性能优化
serializer = ExamTestListSerializer(instance=queryset, many=True)
path = export_test(serializer.data)
return Response({'path': path})
class PaperViewSet(ModelViewSet):
"""
押题卷增删改查

View File

@ -1,22 +1,26 @@
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
import json
from utils.custom import CommonPagination
from .models import Questioncat, Question
from .serializers import QuestioncatSerializer, QuestionSerializer, SubjectSerializer, QuestioncatSerializerDefault
from server import settings
from django_filters.rest_framework import DjangoFilterBackend
from openpyxl import Workbook, load_workbook
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.generics import GenericAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from crm.models import PaySubject
from examtest.models import WorkScope
from server import settings
from utils.custom import CommonPagination
from .models import Question, Questioncat
from .serializers import (QuestioncatSerializer, QuestioncatSerializerDefault,
QuestionSerializer, SubjectSerializer)
class SubjectViewSet(ModelViewSet):
@ -240,4 +244,4 @@ class ExerciseView(APIView):
i['is_collect'] = True
else:
i['is_collect'] = False
return Response({'count':count, 'results':results})
return Response({'count':count, 'results':results})

View File

@ -15,7 +15,7 @@ class UploadFileView(APIView):
def post(self, request, *args, **kwargs):
fileobj = request.FILES['file']
file_name = fileobj.name.encode('utf-8').decode('utf-8')
file_name_new = str(uuid.uuid1()) + '.' + file_name.split('.')[1]
file_name_new = str(uuid.uuid1()) + '.' + file_name.split('.')[-1]
subfolder = os.path.join('media', datetime.now().strftime("%Y%m%d"))
if not os.path.exists(subfolder):
os.mkdir(subfolder)