Commit d0942ce8 authored by zhengjinlei's avatar zhengjinlei

新增两个报表

parent 02673992
...@@ -21,5 +21,6 @@ pytest-django ...@@ -21,5 +21,6 @@ pytest-django
pyyaml pyyaml
raven raven
whitenoise whitenoise
pypinyin==0.36.0
# 私有库包 # 私有库包
...@@ -12,6 +12,7 @@ from config.config import TABLE_PRE ...@@ -12,6 +12,7 @@ from config.config import TABLE_PRE
from django.views.decorators.clickjacking import xframe_options_exempt from django.views.decorators.clickjacking import xframe_options_exempt
from inspect_report import permissions from inspect_report import permissions
import logging import logging
from pypinyin import Style, pinyin
from functools import reduce from functools import reduce
...@@ -292,19 +293,23 @@ class TasksApi(viewsets.ViewSet): ...@@ -292,19 +293,23 @@ class TasksApi(viewsets.ViewSet):
else: else:
task_dict[t['sessionCollectionId']] = [t['id'], ] task_dict[t['sessionCollectionId']] = [t['id'], ]
return_data = {'total_session': 0, 'validate_session': 0} return_data = {'total_session': 0, 'validate_session': 0}
total_score = 0
for k, v in task_dict.items(): for k, v in task_dict.items():
table_name = TABLE_PRE + k table_name = TABLE_PRE + k
tn = CheckSession.set_table(table_name) tn = CheckSession.set_table(table_name)
session_condition = {'taskId__in': v} session_condition = {'taskId__in': v}
checks = tn.objects.filter(**session_condition).values('violationRuleCount') checks = tn.objects.filter(**session_condition).values('violationRuleCount', 'score')
for check in checks: for check in checks:
total_score += check['score']
return_data['total_session'] += 1 return_data['total_session'] += 1
if check['violationRuleCount'] > 0: if check['violationRuleCount'] > 0:
return_data['validate_session'] += 1 return_data['validate_session'] += 1
if return_data['total_session']: if return_data['total_session']:
return_data['ratio'] = round(return_data['validate_session']/return_data['total_session'], 2) return_data['ratio'] = round(return_data['validate_session']/return_data['total_session'], 2)
return_data['avg_score'] = round(total_score / return_data['total_session'], 2)
else: else:
return_data['ratio'] = 0.0 return_data['ratio'] = 0.0
return_data['avg_score'] = 0.0
return Response({'code': 0, 'msg': 'success', 'data': return_data}) return Response({'code': 0, 'msg': 'success', 'data': return_data})
@action(['post'], detail=False) @action(['post'], detail=False)
...@@ -356,6 +361,171 @@ class TasksApi(viewsets.ViewSet): ...@@ -356,6 +361,171 @@ class TasksApi(viewsets.ViewSet):
data_sort = sorted(data_sort, key=lambda x: x['date'], reverse=True) data_sort = sorted(data_sort, key=lambda x: x['date'], reverse=True)
return Response({'code': 0, 'msg': 'success', 'data': data_sort}) return Response({'code': 0, 'msg': 'success', 'data': data_sort})
@action(['post'], detail=False)
def seat_check(self, req: Request):
"""
坐席绩效考核汇总
:param req:
:return:
"""
task_id = req.data.get('task', '')
agent_name = req.data.get('agentName', '')
start_date = req.data.get('start_date', (datetime.now() + timedelta(days=-1)).strftime('%Y-%m-%d'))
end_date = req.data.get('end_date', datetime.now().strftime('%Y-%m-%d'))
task_condition = {'hasCheck': 1, 'createdAt__gte': start_date, 'createdAt__lt': end_date + ' 23:59:59'}
if task_id:
task_condition['name__startswith'] = task_id
tasks = Tasks.objects.filter(**task_condition).values('id', 'name', 'sessionCollectionId')
task_dict = {}
task_name_dict = {}
for t in tasks:
task_name_dict[t['id']] = t['name']
if t['sessionCollectionId'] in task_dict.keys():
task_dict[t['sessionCollectionId']].append(t['id'])
else:
task_dict[t['sessionCollectionId']] = [t['id'], ]
return_data = []
for k, v in task_dict.items():
# session_collection = t.sessionCollectionId
table_name = TABLE_PRE + k
tn = CheckSession.set_table(table_name)
session_condition = {'taskId__in': v}
if agent_name:
session_condition['agentName'] = agent_name
checks = tn.objects.filter(**session_condition).values('id', 'createdAt', 'agentName', 'extra', 'taskId',
'remainTime', 'scoreItemRecord', 'sessionId')
for check in checks:
result = check['scoreItemRecord']
t_name = task_name_dict[check['taskId']]
total_score = 100
detail = {'id': check['id'], 'sessionId': check['sessionId'], 'createdAt': check['createdAt'],
'area': t_name.split('_')[0], 'agentName': check['agentName'], 'filename': check['extra'],
'remainTime': check['remainTime']}
rule_detail = {'fwyy': 10, 'kcb': 10, 'jsy': 5, 'fwtd': 10, 'yssb': 5, 'jysb': 5, 'yycl': 10,
'ywcc': 15, 'yyjlz': 15, 'fwjs': 5, 'wtgbj': 5, 'wzyhfljs': 5, 'wgzlf': 100, 'mgc': 100}
if result:
data = json.loads(result)
for d in data:
if 'scoreItemName' in d.keys() and 'score' in d.keys():
item_score = 0 if d['score'] and d['score'] > 0 else 1
name_py = pinyin(d['scoreItemName'], style=Style.FIRST_LETTER, strict=False)
item_name = ''.join([x[0] for x in name_py])
# detail[item_name] = {d['scoreItemName']: item_score}
if item_name in rule_detail.keys():
if item_score == 0:
total_score -= rule_detail[item_name]
rule_detail[item_name] = item_score
for kk, vv in rule_detail.items():
if vv > 1:
rule_detail[kk] = 1
if rule_detail['wgzlf'] == 0 or rule_detail['mgc'] == 0:
total_score = 0
detail.update(rule_detail)
detail['total_score'] = total_score
return_data.append(detail)
return Response({'code': 0, 'msg': 'success', 'data': return_data})
@action(['post'], detail=False)
def seat_area(self, req: Request):
"""
地市坐席成绩分析
:param req:
:return:
"""
task_id = req.data.get('task', '')
agent_name = req.data.get('agentName', '')
start_date = req.data.get('start_date', (datetime.now() + timedelta(days=-1)).strftime('%Y-%m-%d'))
end_date = req.data.get('end_date', datetime.now().strftime('%Y-%m-%d'))
task_condition = {'hasCheck': 1, 'createdAt__gte': start_date, 'createdAt__lt': end_date + ' 23:59:59'}
if task_id:
task_condition['name__startswith'] = task_id
tasks = Tasks.objects.filter(**task_condition).values('id', 'name', 'sessionCollectionId')
task_dict = {}
task_name_dict = {}
for t in tasks:
task_name_dict[t['id']] = t['name']
if t['sessionCollectionId'] in task_dict.keys():
task_dict[t['sessionCollectionId']].append(t['id'])
else:
task_dict[t['sessionCollectionId']] = [t['id'], ]
return_data = []
detail = {}
for k, v in task_dict.items():
table_name = TABLE_PRE + k
tn = CheckSession.set_table(table_name)
session_condition = {'taskId__in': v}
if agent_name:
session_condition['agentName'] = agent_name
checks = tn.objects.filter(**session_condition).values('id', 'agentName', 'taskId', 'sessionId', 'score')
for check in checks:
if check['agentName'] in detail.keys():
pre_score = detail[check['agentName']]['avg_score']
detail[check['agentName']]['avg_score'] = (pre_score + check['score']) / 2
else:
area_name = task_name_dict[check['taskId']].split('_')[0]
detail[check['agentName']] = {'area': area_name, 'avg_score': check['score']}
for k, v in detail.items():
v['agentName'] = k
return_data.append(v)
return Response({'code': 0, 'msg': 'success', 'data': return_data})
@action(['post'], detail=False)
def static_rule(self, req: Request):
"""
首页概述-违规项统计
:param req:
:return:
"""
task_id = req.data.get('task', '')
agent_name = req.data.get('agentName', '')
start_date = req.data.get('start_date', (datetime.now() + timedelta(days=-1)).strftime('%Y-%m-%d'))
end_date = req.data.get('end_date', datetime.now().strftime('%Y-%m-%d'))
task_condition = {'hasCheck': 1, 'createdAt__gte': start_date, 'createdAt__lt': end_date + ' 23:59:59'}
if task_id:
task_condition['name__startswith'] = task_id
tasks = Tasks.objects.filter(**task_condition).values('id', 'sessionCollectionId')
task_dict = {}
for t in tasks:
if t['sessionCollectionId'] in task_dict.keys():
task_dict[t['sessionCollectionId']].append(t['id'])
else:
task_dict[t['sessionCollectionId']] = [t['id'], ]
return_data = {}
call_count = 0
for k, v in task_dict.items():
table_name = TABLE_PRE + k
tn = CheckSession.set_table(table_name)
session_condition = {'taskId__in': v}
if agent_name:
session_condition['agentName'] = agent_name
checks = tn.objects.filter(**session_condition).values('id', 'checkResult', 'agentName', 'customName',
'remainTime', 'score', 'sessionId', 'taskId')
for check in checks:
call_count += 1
result = check['checkResult']
detail = {'agentName': check['agentName'], 'customName': check['customName'],
'remainTime': check['remainTime'], 'score': check['score'], 'sessionId': check['sessionId'],
'sessionCollectionId': k, 'taskId': check['taskId']}
# session_id = check['id']
if result:
data = json.loads(result)
for d in data:
if 'isViolation' in d.keys() and d['isViolation'] and 'rule' in d.keys() and 'name' in d['rule'].keys():
name = d['rule']['name']
if name in return_data.keys():
return_data[name]['count'] += 1
return_data[name]['details'].append(detail)
else:
return_data[name] = {'count': 1, 'details': [detail, ]}
data_sort = []
for k, v in return_data.items():
v['rule'] = k
v['ratio'] = round(v['count']/call_count, 2)
v['call_count'] = call_count
data_sort.append(v)
data_sort = sorted(data_sort, key=lambda x: x['count'], reverse=True)
return Response({'code': 0, 'msg': 'success', 'data': data_sort})
@xframe_options_exempt @xframe_options_exempt
def rule(request): def rule(request):
...@@ -370,3 +540,13 @@ def seat(request): ...@@ -370,3 +540,13 @@ def seat(request):
@xframe_options_exempt @xframe_options_exempt
def group(request): def group(request):
return render(request, 'inspect/group.html') return render(request, 'inspect/group.html')
@xframe_options_exempt
def score(request):
return render(request, 'inspect/score.html')
@xframe_options_exempt
def check(request):
return render(request, 'inspect/seat_check.html')
...@@ -38,6 +38,9 @@ ...@@ -38,6 +38,9 @@
.groutTitle > div:nth-child(2){ .groutTitle > div:nth-child(2){
margin: 0 10px; margin: 0 10px;
} }
.groutTitle > div:last-child{
margin-left:10px;
}
.groutTitle .grid-content{ .groutTitle .grid-content{
padding: 20px; padding: 20px;
} }
...@@ -58,11 +61,31 @@ ...@@ -58,11 +61,31 @@
</style> </style>
</head> </head>
<body style='height:100%'> <body style='height:100%'>
{# <div class='child-title'>组长概览</div>#} <!--
<div class='child-title'>语音坐席</div>
-->
<div class='child-main' id='childApp' style='background-color:initial;padding:0;'> <div class='child-main' id='childApp' style='background-color:initial;padding:0;'>
<div style='text-align:right;' class='childTitle'> <div style='text-align:right;' class='childTitle'>
<div class='childTitleName'>违规项分析</div> <div class='childTitleName'>违规项分析</div>
<div id='OneTime'> <el-date-picker
v-model="dateRange"
@change='changeRange'
clearable='false'
type="daterange"
value-format='yyyy-MM-dd'
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']">
</el-date-picker>
<el-select v-model="taskvalue" filterable placeholder="请选择" @change="changeTask">
<el-option
v-for="item in taskList"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
<!--
<el-date-picker <el-date-picker
v-model="dateTime" v-model="dateTime"
@change='changeRange' @change='changeRange'
...@@ -71,7 +94,29 @@ ...@@ -71,7 +94,29 @@
type="date" type="date"
> >
</el-date-picker> </el-date-picker>
</div> -->
<!--
<el-select v-model="taskvalue" filterable placeholder="请选择" @change="changeTask">
<el-option
v-for="item in taskList"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
<el-select v-model="takevalue" filterable placeholder="请选择" @change='changeTake'>
<el-option
label="全部坐席"
value="">
</el-option>
<el-option
v-for="item in takeList"
:key="item.agentName"
:label="item.agentName"
:value="item.agentName">
</el-option>
</el-select>
-->
</div> </div>
<div style='margin-top:10px;' class='groutTitle'> <div style='margin-top:10px;' class='groutTitle'>
<div class="grid-content"> <div class="grid-content">
...@@ -104,8 +149,75 @@ ...@@ -104,8 +149,75 @@
<span class='content-value' v-html='titleInfo.ratio * 100 + "%"'>0</span> <span class='content-value' v-html='titleInfo.ratio * 100 + "%"'>0</span>
</div> </div>
</div> </div>
<div class="grid-content">
<div class='icon'>
<i class='el-icon-s-data'></i>
</div>
<div class='content'>
<span>平均分:</span>
<br />
<span class='content-value' v-html='titleInfo.avg_score'>0</span>
</div>
</div>
</div>
<div id='main' style='width:100%;height:600px'>
<el-table
:data="tableData"
border
style="width: 100%;margin-bottom:20px;">
<el-table-column
prop="rule"
label="违规项"
>
</el-table-column>
<el-table-column
prop="count"
label="违规次数"
width="180">
</el-table-column>
<el-table-column
prop="call_count"
label="通话次数">
</el-table-column>
<el-table-column
prop="ratio"
label="违规占比">
</el-table-column>
<el-table-column
label="操作"
width="120">
<template slot-scope="scope">
<el-button
@click.native.prevent="rowDetail(scope.$index, tableData)"
type="text"
size="small">
详情
</el-button>
</template>
</el-table-column>
</el-table>
</div> </div>
<div id='main' style='width:100%;height:600px' v-loading='true'></div> <el-dialog title="详情" :visible.sync="dialogTableVisible">
<el-table style='margin-top:-20px' :data="poptableData" max-height='500'>
<el-table-column prop="agentName" label="坐席id" width='190'></el-table-column>
<el-table-column prop="customName" label="客户" width='190'></el-table-column>
<el-table-column prop="remainTime" label="通话时间(秒)">
{# <template slot-scope='scope'>#}
{# <span>{{formatSeconds(scope.row.remainTime)}}</span>#}
{# </template>#}
</el-table-column>
<el-table-column prop="score" label="分数"></el-table-column>
<el-table-column label="操作">
<template slot-scope='scope'>
<el-button type='text' size="mini" @click="handleTableDetail(scope.$index, scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
<el-button v-if='isscrollTop' @click='backTop' id='backTop' type="warning" icon="el-icon-upload2" circle></el-button>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
window.onload = function(){ window.onload = function(){
......
<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
<meta charset='utf-8' />
<title>质检成绩分析</title>
<!-- 引入样式 -->
<link rel="stylesheet" href="{% static "inspect/css/element.css" %}">
<!-- 引入组件库 -->
<link rel='stylesheet' type='text/css' href='{% static "inspect/css/all.css" %}'>
<style>
#OneTime{
display: inline-block;
}
#OneTime .el-input__icon {
line-height: 32px;
}
#OneTime .el-input .el-input__inner {
padding-left: 30px;
}
.groutTitle span{
display:inline-block;
margin-right: 20px;
color:#565656;
font-size:15px;
}
.groutTitle{
display: flex;
flex-direction: row;
margin-bottom: 20px;
margin-top: 10px;
}
.groutTitle > div{
order: 1;
flex-grow: 1;
background-color:#fff;
}
.groutTitle > div:nth-child(2){
margin: 0 10px;
}
.groutTitle .grid-content{
padding: 20px;
}
.groutTitle .grid-content .icon{
font-size: 30px;
margin-right:10px;
}
.groutTitle .grid-content div{
display: inline-block;
vertical-align: middle;
}
.groutTitle .grid-content .content-value{
font-size: 30px;
}
#main{
background-color: #fff;
}
#mutiTable th {
//text-align:center;
}
#mutiTable .el-table__header tr,
#mutiTable .el-table__header th {
//padding: 0;
//height: 30px;
}
#mutiTable .el-table__body tr,
#mutiTable .el-table__body td {
//padding: 0;
//height: 30px;
}
</style>
</head>
<body style='height:100%'>
<div class='child-title'>语音坐席</div>
<div class='child-main' id='childApp'>
<!--
<div style='text-align:right;' class='childTitle'>
<div class='childTitleName'>违规项分析</div>
<div id='OneTime'>
<el-date-picker
v-model="dateTime"
@change='changeRange'
value-format='yyyy-MM-dd'
clearable='false'
type="date"
>
</el-date-picker>
</div>
</div>
-->
<div style='text-align:right;margin-bottom:15px;' class='childTitle'>
<div class='childTitleName'>地市质检成绩分析</div>
<el-date-picker
v-model="dateRange"
@change='changeRange'
clearable='false'
type="daterange"
value-format='yyyy-MM-dd'
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']">
</el-date-picker>
<el-select v-model="taskvalue" filterable placeholder="请选择" @change="changeTask">
<el-option
v-for="item in taskList"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
<el-select v-model="takevalue" filterable placeholder="请选择" @change='changeTake'>
<el-option
label="全部工号"
value="">
</el-option>
<el-option
v-for="item in takeList"
:key="item.agentName"
:label="item.agentName"
:value="item.agentName">
</el-option>
</el-select>
</div>
<div style='margin-top:10px;' class='groutTitle'>
<el-table
:data="tableData"
id='mutiTable'
border
style="width: 100%">
<el-table-column
prop="area"
label="地市"
width="150">
</el-table-column>
<el-table-column
prop="agentName"
label="工号"
width="190">
</el-table-column>
<el-table-column
prop="avg_score"
label="平均分"
>
</el-table-column>
</el-table>
</div>
<el-button v-if='isscrollTop' @click='backTop' id='backTop' type="warning" icon="el-icon-upload2" circle></el-button>
</div>
<script type="text/javascript">
window.onload = function(){
};
</script>
<script src="{% static "inspect/js/vue.min.js" %}"></script>
<script src="{% static "inspect/js/element.js" %}"></script>
<script src="{% static "inspect/js/http.js" %}"></script>
<script type="text/javascript" src="{% static "inspect/js/score.js" %}"></script>
</body>
</html>
<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
<meta charset='utf-8' />
<title>质检绩效考核汇总</title>
<!-- 引入样式 -->
<link rel="stylesheet" href="{% static "inspect/css/element.css" %}">
<!-- 引入组件库 -->
<link rel='stylesheet' type='text/css' href='{% static "inspect/css/all.css" %}'>
<style>
#OneTime{
display: inline-block;
}
#OneTime .el-input__icon {
line-height: 32px;
}
#OneTime .el-input .el-input__inner {
padding-left: 30px;
}
.groutTitle span{
display:inline-block;
margin-right: 20px;
color:#565656;
font-size:15px;
}
.groutTitle{
display: flex;
flex-direction: row;
margin-bottom: 20px;
margin-top: 10px;
}
.groutTitle > div{
order: 1;
flex-grow: 1;
background-color:#fff;
}
.groutTitle > div:nth-child(2){
margin: 0 10px;
}
.groutTitle .grid-content{
padding: 20px;
}
.groutTitle .grid-content .icon{
font-size: 30px;
margin-right:10px;
}
.groutTitle .grid-content div{
display: inline-block;
vertical-align: middle;
}
.groutTitle .grid-content .content-value{
font-size: 30px;
}
#main{
background-color: #fff;
}
#mutiTable th {
text-align:center;
}
#mutiTable .el-table__header tr,
#mutiTable .el-table__header th {
padding: 0;
height: 30px;
}
#mutiTable .cell{
white-space:nowrap;
}
#mutiTable .el-table__body tr,
#mutiTable .el-table__body td {
padding: 0;
height: 30px;
}
#mutiTable .el-table__body tr:nth-child(2),#mutiTable .el-table__body tr:nth-child(1){
background-color:#f5f7fa;
color:#909399;
font-weight: bold;
}
#mutiTable .el-table__body tr:nth-child(2) td:first-child,#mutiTable .el-table__body tr:nth-child(1) td:first-child{
border-right: 0;
}
#noData{
text-align: center;
height: 300px;
margin: 0;
line-height: 300px;
border: 1px solid #ebeef5;
color:#606266;
}
</style>
</head>
<body style='height:100%'>
<div class='child-title'>语音坐席</div>
<div class='child-main' id='childApp'>
<!--
<div style='text-align:right;' class='childTitle'>
<div class='childTitleName'>违规项分析</div>
<div id='OneTime'>
<el-date-picker
v-model="dateTime"
@change='changeRange'
value-format='yyyy-MM-dd'
clearable='false'
type="date"
>
</el-date-picker>
</div>
</div>
-->
<div style='text-align:right;margin-bottom:15px;' class='childTitle'>
<div class='childTitleName'>质检绩效考核汇总</div>
<el-date-picker
v-model="dateRange"
@change='changeRange'
clearable='false'
type="daterange"
value-format='yyyy-MM-dd'
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']">
</el-date-picker>
<el-select v-model="taskvalue" filterable placeholder="请选择" @change="changeTask">
<el-option
v-for="item in taskList"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
<el-select v-model="takevalue" filterable placeholder="请选择" @change='changeTake'>
<el-option
label="全部坐席"
value="">
</el-option>
<el-option
v-for="item in takeList"
:key="item.agentName"
:label="item.agentName"
:value="item.agentName">
</el-option>
</el-select>
</div>
<div style='margin-top:10px;display:block;' class='groutTitle'>
<el-table
:data="tableData"
v-if='tableData.length != 2'
size='min'
:span-method='arraySpanMethod'
id='mutiTable'
style="width: 100%">
<el-table-column
prop="createdAt"
label="时间"
width="180">
</el-table-column>
<el-table-column
prop="agentName"
label="坐席工号"
width="180">
</el-table-column>
<el-table-column
prop="filename"
label="文件名"
width="">
<template slot-scope="scope">
<span style='cursor:pointer;' :title='scope.row.filename'>{{scope.row.filename}}</span>
</template>
</el-table-column>
<el-table-column
prop="remainTime"
label="通话时长(s)"
width="100">
</el-table-column>
<el-table-column
label="服务类(45%)"
>
<el-table-column
prop="fwyy"
label="服务用语"
width="">
</el-table-column>
<el-table-column
prop="kcb"
label="开场白"
width="">
</el-table-column>
<el-table-column
prop="jsy"
label="结束语"
width="">
</el-table-column>
<el-table-column
prop="fwtd"
label="服务态度"
width="">
</el-table-column>
<el-table-column
prop="yssb"
label="语速识别"
width="">
</el-table-column>
<el-table-column
prop="jysb"
label="静音识别"
width="">
</el-table-column>
</el-table-column>
<el-table-column
label="业务类(55%)"
>
<el-table-column
prop="yycl"
label="异议处理"
width="">
</el-table-column>
<el-table-column
prop="ywcc"
label="业务促成"
width="">
</el-table-column>
<el-table-column
prop="yyjlz"
label="预约及流转"
width="100">
</el-table-column>
<el-table-column
prop="fwjs"
label="服务介绍"
width="">
</el-table-column>
<el-table-column
prop="wtgbj"
label="未提供报价"
width="100">
</el-table-column>
<el-table-column
prop="wzyhfljs"
label="未做优惠费率介绍"
width="140">
</el-table-column>
</el-table-column>
<el-table-column
label="0分项"
>
<el-table-column
prop="wgzlf"
label="违规则0分"
width="100">
</el-table-column>
<el-table-column
prop="mgc"
label="敏感词"
width="">
</el-table-column>
</el-table-column>
<el-table-column
prop="total_score"
label="得分"
>
</el-table-column>
</el-table>
<div v-else id='noData'>暂无数据!</div>
</div>
<el-button v-if='isscrollTop' @click='backTop' id='backTop' type="warning" icon="el-icon-upload2" circle></el-button>
</div>
<script type="text/javascript">
window.onload = function(){
};
</script>
<script src="{% static "inspect/js/vue.min.js" %}"></script>
<script src="{% static "inspect/js/element.js" %}"></script>
<script src="{% static "inspect/js/http.js" %}"></script>
<script type="text/javascript" src="{% static "inspect/js/mutiHeadTable.js" %}"></script>
</body>
</html>
...@@ -15,11 +15,13 @@ Including another URLconf ...@@ -15,11 +15,13 @@ Including another URLconf
""" """
from django.contrib import admin from django.contrib import admin
from django.urls import path from django.urls import path
from .api.tasksapi import rule, seat, group from .api.tasksapi import rule, seat, group, score, check
urlpatterns = [ urlpatterns = [
# path('admin/', admin.site.urls), # path('admin/', admin.site.urls),
path('inspect/rule/', rule), path('inspect/rule/', rule),
path('inspect/seat/', seat), path('inspect/seat/', seat),
path('inspect/group/', group), path('inspect/group/', group),
path('inspect/score/', score),
path('inspect/check/', check),
] ]
...@@ -116,4 +116,10 @@ body{ ...@@ -116,4 +116,10 @@ body{
} }
.childStatistics > div > div{ .childStatistics > div > div{
width: 500px; width: 500px;
} }
\ No newline at end of file #backTop{
position: fixed;
bottom: 0px;
right: 0px;
z-index:1000;
}
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
...@@ -234,17 +234,11 @@ new Vue({ ...@@ -234,17 +234,11 @@ new Vue({
return date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate(); return date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate();
}, },
handleTableDetail(index, msg){ handleTableDetail(index, msg){
console.log('hehhe') let url = "/quality/audio/check-detail/"+msg.sessionCollectionId+"/"+msg.taskId+"?from=checkTask&sessionId=" + msg.sessionId;
console.log(msg);
let url = "/quality/audio/check-detail/"+msg.sessionCollectionId+"/"+msg.taskId+"?from=checkTask&sessionId=" + msg.sessionId;
let autoMessage = { let autoMessage = {
//id: msg.id jumplink: url
// sessionCollectionId: msg.sessionCollectionId,
// sessionId: msg.sessionId,
// taskId: msg.taskId
jumplink: url
}; };
console.log(autoMessage) console.log(autoMessage);
window.parent.postMessage(autoMessage,'*'); window.parent.postMessage(autoMessage,'*');
}, },
init(){ init(){
......
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
...@@ -7,8 +7,12 @@ new Vue({ ...@@ -7,8 +7,12 @@ new Vue({
taskList:[], taskList:[],
taskvalue: '', taskvalue: '',
start_date: '', start_date: '',
isscrollTop: false,
scrollTop: 0,
end_date:'', end_date:'',
dialogTableVisible: false,
takeList:[], takeList:[],
dateRange:[new Date(), new Date()],
takevalue: '', takevalue: '',
titleInfo: { titleInfo: {
"total_session": 0, "total_session": 0,
...@@ -16,23 +20,31 @@ new Vue({ ...@@ -16,23 +20,31 @@ new Vue({
"ratio": 0, "ratio": 0,
}, },
loading: true, loading: true,
poptableData: [],
tableData: []
} }
}, },
mounted () {
window.addEventListener('scroll', this.scrollToTop)
},
destroyed () {
window.removeEventListener('scroll', this.scrollToTop)
},
methods: { methods: {
changeRange(dateTime){ changeRange(dateRange){
console.log(dateTime); this.start_date = dateRange[0];
this.start_date = dateTime; this.end_date = dateRange[1];
this.getRule(this.taskvalue,this.start_date,this.takevalue); // 获取统计数据 this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
}, },
changeTask(msg){ changeTask(msg){
console.log(msg); console.log(msg);
this.taskvalue = msg; this.taskvalue = msg;
this.getTake() this.getTake()
this.getRule(this.taskvalue,this.start_date,this.takevalue); // 获取统计数据 this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
}, },
changeTake(msg){ changeTake(msg){
this.takevalue = msg; this.takevalue = msg;
this.getRule(this.taskvalue,this.start_date,this.takevalue); // 获取统计数据 this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
console.log(msg); console.log(msg);
}, },
getTask(){ getTask(){
...@@ -80,78 +92,13 @@ new Vue({ ...@@ -80,78 +92,13 @@ new Vue({
} }
}) })
}, },
Charts(msg){ getRule(task,start_date,end_date,agentName){
console.log(msg);
let msgLen = msg.length;
let xAxisArr = [];
let seriesArr = [];
for(let key in msg){
console.log(key);
xAxisArr.unshift(msg[key].date);
seriesArr.unshift(msg[key].ratio * 100);
}
let option = {
tooltip: {
trigger: 'axis',
//formatter: '违规率:<br />{c}%'
formatter: '违规率:{c}%'
},
xAxis: {
type: 'category',
//data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
data: xAxisArr
},
yAxis: {
//name: 'amount',
max:'100',
type: 'value',
axisLabel:{
formatter: '{value}%'
}
},
series: [{
//data: [820, 932, 901, 934, 1290, 1330, 1320],
name:'违规率',
data: seriesArr,
type: 'line',
smooth: true,
itemStyle:{
normal:{
color: '#fccb04'
},
emphasis:{
color: '#f7d139'
}
},
}]
};
var myChart = echarts.init(document.getElementById('main'));
myChart.setOption(option)
if(msg.length == 0){
myChart.showLoading({
text: '暂无数据',
color: '#ffffff',
textColor: '#8a8e91',
maskColor: 'rgba(255, 255, 255, 0.8)',
});
}else{
myChart.hideLoading();
}
window.onresize = function(){
myChart.resize();
}
},
getRule(task,end_date,agentName){
let that = this; let that = this;
let start_date = this.dateFormat(new Date(new Date(end_date).getTime() - 6*24*60*60*1000));
console.log(start_date,end_date); console.log(start_date,end_date);
let arr = []; let arr = [];
this.$loading({text:'数据加载中...'}); this.$loading({text:'数据加载中...'});
RquestsPost('api/v1/tasks/static_date/',{task,end_date,start_date,agentName}).then(data => { RquestsPost('api/v1/tasks/static_rule/',{task,end_date,start_date,agentName}).then(data => {
console.log(data.data); console.log(data.data);
if(data.code != 0){ if(data.code != 0){
that.$message(data.msg); that.$message(data.msg);
...@@ -169,8 +116,7 @@ new Vue({ ...@@ -169,8 +116,7 @@ new Vue({
//for(let key in data.data){ //for(let key in data.data){
// arr.unshift([data.data[key],key]) // arr.unshift([data.data[key],key])
//} //}
this.tableData = data.data;
that.Charts(data.data);
this.$loading().close(); this.$loading().close();
}) })
RquestsPost('api/v1/tasks/static/',{task,end_date,start_date,agentName}).then(data => { RquestsPost('api/v1/tasks/static/',{task,end_date,start_date,agentName}).then(data => {
...@@ -189,19 +135,56 @@ new Vue({ ...@@ -189,19 +135,56 @@ new Vue({
return false; return false;
} }
that.titleInfo = data.data; that.titleInfo = data.data;
this.$loading().close(); //this.$loading().close();
}) })
}, },
dateFormat(date){ dateFormat(date){
return date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate(); return date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate();
}, },
rowDetail(index,tableData){
console.log(tableData[index]);
//console.log(tableData);
this.poptableData = tableData[index].details;
this.dialogTableVisible = true;
},
handleTableDetail(index, msg){
let url = "/quality/audio/check-detail/"+msg.sessionCollectionId+"/"+msg.taskId+"?from=checkTask&sessionId=" + msg.sessionId;
console.log(url);
let autoMessage = {
jumplink: url
};
window.parent.postMessage(autoMessage,'*');
},
backTop () {
const that = this
let timer = setInterval(() => {
let ispeed = Math.floor(-that.scrollTop / 5)
document.documentElement.scrollTop = document.body.scrollTop = that.scrollTop + ispeed
if (that.scrollTop === 0) {
clearInterval(timer)
}
}, 16)
},
// 为了计算距离顶部的高度,当高度大于60显示回顶部图标,小于60则隐藏
scrollToTop () {
const that = this
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
that.scrollTop = scrollTop
if (that.scrollTop > 60) {
that.isscrollTop = true
} else {
that.isscrollTop = false
}
},
init(){ init(){
this.dateTime = new Date(new Date()-24*60*60*1000); this.dateRange = [new Date(new Date()-24*60*60*1000), new Date()];
this.start_date = this.dateFormat(new Date(new Date()-24*60*60*1000)); this.start_date = this.dateFormat(new Date(new Date()-24*60*60*1000));
this.end_date = this.dateFormat(new Date());
this.getTask(); // 获取任务 this.getTask(); // 获取任务
//this.getTake(); // 获取坐席 //this.getTake(); // 获取坐席
this.getRule(this.taskvalue,this.start_date,this.takevalue); // 获取统计数据 this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
} }
}, },
......
// let window_url = "http://127.0.0.1:8099/"; //let window_url = "http://192.168.1.156:8099/";
let window_url = window.location.protocol + "//" + window.location.host + "/"; let window_url = window.location.protocol + "//" + window.location.host + "/";
function RquestsGet(url){ function RquestsGet(url){
......
new Vue({
el: '#childApp',
data:function(){
return {
ss:'sas',
dateTime: '',
taskList:[],
isscrollTop: false,
scrollTop: 0,
taskvalue: '',
dateRange:[new Date(), new Date()],
start_date: '',
end_date:'',
takeList:[],
takevalue: '',
loading: true,
tableData: [
{
createdAt: '质检考核项目编号',
fwyy:'1',
kcb:'2',
jsy:'3',
fwtd:'4',
yssb:'5',
jysb:'6',
yycl:'7',
ywcc:'8',
yyjlz:'9',
fwjs:'10',
wtgbj:'11',
wzyhfljs:'12',
wgzlf:'13',
mgc:'14',
}, {
createdAt: '质检考核项目编号',
fwyy:'10%',
kcb:'10%',
jsy:'5%',
fwtd:'10%',
yssb:'5%',
jysb:'5%',
yycl:'10%',
ywcc:'15%',
yyjlz:'15%',
fwjs:'5%',
wtgbj:'5%',
wzyhfljs:'5%',
wgzlf:'100%',
mgc:'100%',
}]
}
},
mounted () {
window.addEventListener('scroll', this.scrollToTop)
},
destroyed () {
window.removeEventListener('scroll', this.scrollToTop)
},
methods: {
changeRange(dateRange){
this.start_date = dateRange[0];
this.end_date = dateRange[1];
this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
},
changeTask(msg){
this.taskvalue = msg;
this.getTake()
this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
},
changeTake(msg){
this.takevalue = msg;
this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
},
getTask(){
let that = this;
that.taskList = [
{id:'',name:'全省'},
{id:'合肥',name:'合肥'},
{id:'芜湖',name:'芜湖'},
{id:'蚌埠',name:'蚌埠'},
{id:'淮南',name:'淮南'},
{id:'马鞍山',name:'马鞍山'},
{id:'淮北',name:'淮北'},
{id:'铜陵',name:'铜陵'},
{id:'安庆',name:'安庆'},
{id:'黄山',name:'黄山'},
{id:'滁州',name:'滁州'},
{id:'阜阳',name:'阜阳'},
{id:'毫州',name:'毫州'},
{id:'宿州',name:'宿州'},
{id:'六安',name:'六安'},
{id:'宣城',name:'宣城'},
{id:'巢湖',name:'巢湖'},
{id:'池州',name:'池州'},
{id:'安徽省营业部',name:'安徽省营业部'},
];
},
getRule(task,start_date,end_date,agentName){
let that = this;
this.$loading({text:'数据加载中...'});
RquestsPost('api/v1/tasks/seat_check/',{task,start_date,end_date,agentName}).then(data => {
that.$loading().close();
if(data.code != 0){
}else{
let arr = [
{
createdAt: '质检考核项目编号',
fwyy:'1',
kcb:'2',
jsy:'3',
fwtd:'4',
yssb:'5',
jysb:'6',
yycl:'7',
ywcc:'8',
yyjlz:'9',
fwjs:'10',
wtgbj:'11',
wzyhfljs:'12',
wgzlf:'13',
mgc:'14',
}, {
createdAt: '质检考核项目编号',
fwyy:'10%',
kcb:'10%',
jsy:'5%',
fwtd:'10%',
yssb:'5%',
jysb:'5%',
yycl:'10%',
ywcc:'15%',
yyjlz:'15%',
fwjs:'5%',
wtgbj:'5%',
wzyhfljs:'5%',
wgzlf:'100%',
mgc:'100%',
}]
that.tableData = arr.concat(data.data);
//that.takeList = data.data;
}
})
},
getTake(){
let that = this;
RquestsGet('api/v1/tasks/seat/?task=' + that.taskvalue).then(data => {
//console.log(data);
if(data.code != 0){
//that.takeList = [{agentName:'全部坐席'}]
}else{
that.takeList = data.data;
}
})
},
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
console.log(column)
if (rowIndex === 0 || rowIndex === 1) { // 在这里多加一个行的判断就行
// 合并第二行
if (columnIndex === 0) {
// 从第二列开始
return [1, 3]
}
else if (columnIndex === 2 || columnIndex === 3 ) {
return [0, 0]
}
}
},
dateFormat(date){
return date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate();
},
backTop () {
const that = this
let timer = setInterval(() => {
let ispeed = Math.floor(-that.scrollTop / 5)
document.documentElement.scrollTop = document.body.scrollTop = that.scrollTop + ispeed
if (that.scrollTop === 0) {
clearInterval(timer)
}
}, 16)
},
// 为了计算距离顶部的高度,当高度大于60显示回顶部图标,小于60则隐藏
scrollToTop () {
const that = this
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
that.scrollTop = scrollTop
if (that.scrollTop > 60) {
that.isscrollTop = true
} else {
that.isscrollTop = false
}
},
init(){
this.dateRange = [new Date(new Date()-24*60*60*1000), new Date()];
this.start_date = this.dateFormat(new Date(new Date()-24*60*60*1000));
this.end_date = this.dateFormat(new Date());
this.getTask(); // 获取任务
this.getTake(); // 获取坐席
this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
}
},
created(){
this.init()
},
})
new Vue({
el: '#childApp',
data:function(){
return {
ss:'sas',
dateTime: '',
taskList:[],
taskvalue: '',
isscrollTop: false,
scrollTop: 0,
dateRange:[new Date(), new Date()],
start_date: '',
end_date:'',
takeList:[],
takevalue: '',
loading: true,
tableData: [],
}
},
mounted () {
window.addEventListener('scroll', this.scrollToTop)
},
destroyed () {
window.removeEventListener('scroll', this.scrollToTop)
},
methods: {
changeRange(dateRange){
this.start_date = dateRange[0];
this.end_date = dateRange[1];
this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
},
changeTask(msg){
this.taskvalue = msg;
this.getTake()
this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
},
changeTake(msg){
this.takevalue = msg;
this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
},
getTask(){
let that = this;
that.taskList = [
{id:'',name:'全省'},
{id:'合肥',name:'合肥'},
{id:'芜湖',name:'芜湖'},
{id:'蚌埠',name:'蚌埠'},
{id:'淮南',name:'淮南'},
{id:'马鞍山',name:'马鞍山'},
{id:'淮北',name:'淮北'},
{id:'铜陵',name:'铜陵'},
{id:'安庆',name:'安庆'},
{id:'黄山',name:'黄山'},
{id:'滁州',name:'滁州'},
{id:'阜阳',name:'阜阳'},
{id:'毫州',name:'毫州'},
{id:'宿州',name:'宿州'},
{id:'六安',name:'六安'},
{id:'宣城',name:'宣城'},
{id:'巢湖',name:'巢湖'},
{id:'池州',name:'池州'},
{id:'安徽省营业部',name:'安徽省营业部'},
];
},
getRule(task,start_date,end_date,agentName){
let that = this;
this.$loading({text:'数据加载中...'});
RquestsPost('api/v1/tasks/seat_area/',{task,start_date,end_date,agentName}).then(data => {
if(data.code != 0){
//that.takeList = [{agentName:'全部坐席'}]
}else{
that.tableData = data.data;
}
that.$loading().close();
})
},
getTake(){
let that = this;
RquestsGet('api/v1/tasks/seat/?task=' + that.taskvalue).then(data => {
//console.log(data);
if(data.code != 0){
//that.takeList = [{agentName:'全部坐席'}]
}else{
that.takeList = data.data;
}
})
},
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
if (rowIndex === 0 || rowIndex === 1) { // 在这里多加一个行的判断就行
// 合并第二行
if (columnIndex === 0) {
// 从第二列开始
return [1, 6]
} else if (columnIndex === 2 || columnIndex === 3 || columnIndex === 4 || columnIndex === 5 || columnIndex === 6) {
return [0, 0]
}
}
},
dateFormat(date){
return date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate();
},
backTop () {
const that = this
let timer = setInterval(() => {
let ispeed = Math.floor(-that.scrollTop / 5)
document.documentElement.scrollTop = document.body.scrollTop = that.scrollTop + ispeed
if (that.scrollTop === 0) {
clearInterval(timer)
}
}, 16)
},
// 为了计算距离顶部的高度,当高度大于60显示回顶部图标,小于60则隐藏
scrollToTop () {
const that = this
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
that.scrollTop = scrollTop
if (that.scrollTop > 60) {
that.isscrollTop = true
} else {
that.isscrollTop = false
}
},
init(){
this.dateRange = [new Date(new Date()-24*60*60*1000), new Date()];
this.start_date = this.dateFormat(new Date(new Date()-24*60*60*1000));
this.end_date = this.dateFormat(new Date());
this.getTask(); // 获取任务
this.getTake(); // 获取坐席
this.getRule(this.taskvalue,this.start_date,this.end_date,this.takevalue); // 获取统计数据
}
},
created(){
this.init()
},
})
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment