export
This commit is contained in:
parent
875069ac9f
commit
426c2fdae1
|
@ -6,3 +6,4 @@ export function getBasicCount() {
|
|||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
|
@ -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
|
||||
})
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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");
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
押题卷增删改查
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue