Commit 70145385 authored by 赵茹林's avatar 赵茹林

Merge branch 'dev' into pre

parents 61cf67b3 a1d10c9a
...@@ -21,15 +21,16 @@ module.exports = { ...@@ -21,15 +21,16 @@ module.exports = {
output: { output: {
path: config.build.assetsRoot, path: config.build.assetsRoot,
filename: '[name].js', filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production' publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
}, },
resolve: { resolve: {
extensions: ['.js', '.vue', '.json'], extensions: ['.js', '.vue', '.json'],
alias: { alias: {
'vue$': 'vue/dist/vue.esm.js', 'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'), '@': resolve('src'),
'@util': resolve('src/util'),
'@service': resolve('src/service'),
'@framework': resolve('src/components/framework'),
} }
}, },
module: { module: {
......
...@@ -22,6 +22,7 @@ const devWebpackConfig = merge(baseWebpackConfig, { ...@@ -22,6 +22,7 @@ const devWebpackConfig = merge(baseWebpackConfig, {
// these devServer options should be customized in /config/index.js // these devServer options should be customized in /config/index.js
devServer: { devServer: {
disableHostCheck: true,
clientLogLevel: 'warning', clientLogLevel: 'warning',
historyApiFallback: { historyApiFallback: {
rewrites: [ rewrites: [
...@@ -34,14 +35,14 @@ const devWebpackConfig = merge(baseWebpackConfig, { ...@@ -34,14 +35,14 @@ const devWebpackConfig = merge(baseWebpackConfig, {
host: HOST || config.dev.host, host: HOST || config.dev.host,
port: PORT || config.dev.port, port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser, open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false,
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath, publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable, proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: { watchOptions: {
poll: config.dev.poll, poll: config.dev.poll,
aggregateTimeout: 500,
ignored : ['static', 'dist', 'dev', 'node_modules', 'src/assets'],
} }
}, },
plugins: [ plugins: [
...@@ -84,9 +85,7 @@ module.exports = new Promise((resolve, reject) => { ...@@ -84,9 +85,7 @@ module.exports = new Promise((resolve, reject) => {
compilationSuccessInfo: { compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
}, },
onErrors: config.dev.notifyOnErrors onErrors: config.dev.notifyOnErrors ? utils.createNotifierCallback() : undefined
? utils.createNotifierCallback()
: undefined
})) }))
resolve(devWebpackConfig) resolve(devWebpackConfig)
......
...@@ -33,7 +33,7 @@ module.exports = { ...@@ -33,7 +33,7 @@ module.exports = {
// Various Dev Server settings // Various Dev Server settings
host: getIP(), // can be overwritten by process.env.HOST host: getIP(), // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false, autoOpenBrowser: true,
errorOverlay: true, errorOverlay: true,
notifyOnErrors: true, notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
......
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=referrer content=never><link rel=stylesheet href=https://at.alicdn.com/t/font_746649_x1rivf5f5.css><link rel=stylesheet href=https://lib.baomitu.com/element-ui/2.11.1/theme-chalk/index.css><title>唱唱启蒙-后台</title></head><body><script src=https://lib.baomitu.com/vue/2.5.17/vue.js></script><script src=https://lib.baomitu.com/vuex/3.0.1/vuex.min.js></script><script src=https://lib.baomitu.com/axios/0.18.0/axios.min.js></script><script src=https://lib.baomitu.com/element-ui/2.11.1/index.js></script><div id=app></div><script type=text/javascript src=/static/js/manifest.4fa8c3e44c5f2cb7e588.js></script><script type=text/javascript src=/static/js/vendor.fdfa49e267f48089768a.js></script><script type=text/javascript src=/static/js/app.771316ce36eae7e98b65.js></script></body><script>let el = document.getElementsByTagName("script");
el.onerror = function(a,b,c){
console.log('error:',a,b,c);
};
// document.getElementsByTagName('script').onerror</script></html>
\ No newline at end of file
...@@ -283,6 +283,27 @@ ...@@ -283,6 +283,27 @@
border-radius: 50%; border-radius: 50%;
height: 50px; height: 50px;
} }
.table-refresh-header {
display: inline-block;
cursor: help;
i {
color: #409eff;
}
}
.cell-link {
display: inline-block;
margin: 0 -6px;
padding: 0px 8px;
border-radius: 3px;
text-decoration: underline;
transition: color 240ms, background-color 240ms;
&:hover {
background-color: #cce4ff;
color: #007fff;
}
}
} }
.update-time { .update-time {
......
...@@ -154,6 +154,7 @@ ...@@ -154,6 +154,7 @@
this.form = { this.form = {
teacher_id:'', teacher_id:'',
max_join_num:'', max_join_num:'',
class_name: '',
source:'', source:'',
qr:"" qr:""
}; };
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<div class="search-btn-wrapper"> <div class="search-btn-wrapper">
<el-button type="primary" plain @click="getList">搜索</el-button> <el-button type="primary" plain @click="getList">搜索</el-button>
<!--<el-button v-if="!$store.state.readonly" type="primary" plain @click="downLoad()">excel模板下载</el-button>--> <!--<el-button v-if="!$store.state.readonly" type="primary" plain @click="downLoad()">excel模板下载</el-button>-->
<el-button type="success" plain @click="exportTable" v-if="$store.state.export">导出</el-button> <!--<el-button type="warning" plain v-if="$store.state.import">导入</el-button>-->
<el-upload <el-upload
style="margin-left: 10px;" style="margin-left: 10px;"
v-if="$store.state.import" v-if="$store.state.import"
...@@ -27,9 +27,11 @@ ...@@ -27,9 +27,11 @@
:onSuccess="fileSuccess" :onSuccess="fileSuccess"
:headers="uploadHeader" :headers="uploadHeader"
:data="{param_token:param_token}" :data="{param_token:param_token}"
action="/api/admin/order/deliver/list/import"> accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
<el-button type="success" plain>导入发货信息</el-button> action="/api/admin/deliver/once/import">
<el-button type="warning" plain>导入发货信息</el-button>
</el-upload> </el-upload>
<el-button style="margin-left: 10px;" type="success" plain @click="exportTable" v-if="$store.state.export">导出</el-button>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -80,8 +82,8 @@ ...@@ -80,8 +82,8 @@
<div style="color: #67c23a;">{{scope.row.status|LogisticsStatusFil}}</div> <div style="color: #67c23a;">{{scope.row.status|LogisticsStatusFil}}</div>
</template> </template>
<!--<template v-if="scope.row.status == 1">--> <!--<template v-if="scope.row.status == 1">-->
<template v-if="scope.row.express_name">{{scope.row.express_name}}</template> <template v-if="scope.row.express_name">{{scope.row.express_name}}</template>
<a v-if="scope.row.express_no" :href="`https://m.baidu.com/from=1013755s/s?word=${scope.row.express_no}&sa=tb&ts=2790568&t_kt=0&ie=utf-8&rsv_t=cbe2F%252FT5T3MIzkRl%252Fg8ZUw%252FEPHZmn2wHIrB8cLvgNlEKyyDqUNPrTyDEEDjkAb8&rsv_pq=11793168499026332712&ss=110000000001&tj=1&rqlang=zh&rsv_sug4=4111&inputT=3178&oq=快递单号查询`" target="_blank">{{scope.row.express_no}}</a> <a v-if="scope.row.express_no" :href="`https://m.baidu.com/from=1013755s/s?word=${scope.row.express_no}&sa=tb&ts=2790568&t_kt=0&ie=utf-8&rsv_t=cbe2F%252FT5T3MIzkRl%252Fg8ZUw%252FEPHZmn2wHIrB8cLvgNlEKyyDqUNPrTyDEEDjkAb8&rsv_pq=11793168499026332712&ss=110000000001&tj=1&rqlang=zh&rsv_sug4=4111&inputT=3178&oq=快递单号查询`" target="_blank">{{scope.row.express_no}}</a>
<!--</template>--> <!--</template>-->
</template> </template>
</el-table-column> </el-table-column>
...@@ -170,9 +172,9 @@ ...@@ -170,9 +172,9 @@
editAddress(row) { editAddress(row) {
console.log(row); console.log(row);
//if (row.status == 1) { //if (row.status == 1) {
this.dialogObj.express_no = row.express_no; this.dialogObj.express_no = row.express_no;
this.dialogObj.express_name = row.express_name; this.dialogObj.express_name = row.express_name;
this.dialogObj.status = row.status; this.dialogObj.status = row.status;
//} //}
this.dialogObj.receive_address = row.receive_address; this.dialogObj.receive_address = row.receive_address;
this.dialogObj.receive_mobile = row.receive_mobile; this.dialogObj.receive_mobile = row.receive_mobile;
......
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
<script> <script>
import headIndex from './headIndex' import headIndex from './headIndex'
import leftMenu from './leftMenu' import leftMenu from './leftMenu'
import tab from './tab' // import tab from './tab'
export default { export default {
components: {leftMenu, headIndex,tab}, components: {leftMenu, headIndex},
data(){ data(){
return { return {
transitionName: 'slide-left', transitionName: 'slide-left',
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
<div class="page-div"> <div class="page-div">
<el-pagination <el-pagination
:small="small" :small="small"
@size-change="handleSizeChange"
:page-sizes="[5, 10, 20, 30, 40, 50, 60, 80, 100]"
:page-size="limit" :page-size="limit"
:current-page.sync="nowPage" :page-sizes="[5, 10, 20, 30, 40, 50, 60, 80, 100]"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="nowPage"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
:total="total"> :total="total">
</el-pagination> </el-pagination>
...@@ -21,6 +22,9 @@ ...@@ -21,6 +22,9 @@
} }
}, },
props: { props: {
'currentPage': {
required: false,
},
'total': { 'total': {
required: true required: true
}, },
...@@ -28,19 +32,29 @@ ...@@ -28,19 +32,29 @@
default: 10 default: 10
}, },
'small': { 'small': {
required: false,
type: Boolean, type: Boolean,
default: false default: false
} }
}, },
watch: { watch: {
nowPage(value) { currentPage(val) { // 改变这个值并不会触发 handleCurrentChange
this.$emit("pageChange", value); if (typeof val === "number") {
} console.log('prop currentPage!!!');
this.nowPage = val;
}
},
}, },
methods: { methods: {
// 当前页变化
handleCurrentChange(val) {
console.log('methods pageChange!!!')
this.$emit("pageChange", val);
},
// size变化
handleSizeChange(val) { handleSizeChange(val) {
this.nowPage = 1;
this.$emit('sizeChange', val); this.$emit('sizeChange', val);
this.nowPage = 1
}, },
} }
} }
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
<script> <script>
import {addPeriodsClassUserDescApi,getUserDescListApi,editUserReplyApi} from "../../service/api"; import {addPeriodsClassUserDescApi,getUserDescListApi,editUserReplyApi} from "../../service/api";
import CallBack from '@/components/callBack/index'; import CallBack from '@/components/userDetail/callBack';
export default { export default {
name: "teacherDesc", name: "teacherDesc",
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
</div> </div>
<div class="subcompany-list"> <div class="subcompany-list">
<div class="subcompany-list-content" v-if="subcompanyList.length > 0"> <div class="subcompany-list-content" v-if="subcompanyList.length > 0">
<el-form :inline="true" v-for="item in subcompanyList" class="demo-form-inline" size="mini"> <el-form :inline="true" :key="item.id" v-for="item in subcompanyList" class="demo-form-inline" size="mini">
<el-form-item label="销售层级"> <el-form-item label="销售层级">
<el-select v-model="item.sale_level" @change="modifyLevel(item.id, item.sale_level)" @focus="focusOldVal(item.sale_level)" placeholder="销售层级"> <el-select v-model="item.sale_level" @change="modifyLevel(item.id, item.sale_level)" @focus="focusOldVal(item.sale_level)" placeholder="销售层级">
<el-option v-for="itemSale in saleLevel" :label="itemSale.label" :value="itemSale.value"></el-option> <el-option :key="itemSale.value" v-for="itemSale in saleLevel" :label="itemSale.label" :value="itemSale.value"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="级别名称"> <el-form-item label="级别名称">
......
...@@ -42,13 +42,13 @@ ...@@ -42,13 +42,13 @@
<el-checkbox v-model="data.refund" v-if="data.cover ==='5-1'|| data.cover=== '5-10'|| data.cover=== '5-9'">退款</el-checkbox> <el-checkbox v-model="data.refund" v-if="data.cover ==='5-1'|| data.cover=== '5-10'|| data.cover=== '5-9'">退款</el-checkbox>
<el-checkbox v-model="data.refund" v-if="data.cover ==='10-1' ">类别管理</el-checkbox> <el-checkbox v-model="data.refund" v-if="data.cover ==='10-1' ">类别管理</el-checkbox>
<el-checkbox v-model="data.promoter" v-if="data.cover ==='5-1' ">编辑推广人</el-checkbox> <el-checkbox v-model="data.promoter" v-if="data.cover ==='5-1' ">编辑推广人</el-checkbox>
<el-checkbox v-model="data.refund" v-if="data.cover ==='2-3'|| data.cover=== '3-1'|| data.cover=== '3-2' ">添加观摩班用户</el-checkbox> <el-checkbox v-model="data.refund" v-if="data.cover ==='2-3'|| data.cover=== '3-1'|| data.cover=== '3-2' || data.cover=== '3-6' || data.cover=== '3-7' ">添加观摩班用户</el-checkbox>
<el-checkbox v-model="data.classManage" v-if="data.cover ==='2-3'|| data.cover=== '3-1'|| data.cover=== '3-2' ">添加带班班用户</el-checkbox> <el-checkbox v-model="data.classManage" v-if="data.cover ==='2-3'|| data.cover=== '3-1'|| data.cover=== '3-2' || data.cover=== '3-6' || data.cover=== '3-7' ">添加带班班用户</el-checkbox>
<el-checkbox v-model="data.classManageUnlimited" v-if="data.cover ==='2-3'|| data.cover=== '3-1'|| data.cover=== '3-2' ">添加观摩班(无限制)</el-checkbox> <el-checkbox v-model="data.classManageUnlimited" v-if="data.cover ==='2-3'|| data.cover=== '3-1'|| data.cover=== '3-2' || data.cover=== '3-6' || data.cover=== '3-7' ">添加观摩班(无限制)</el-checkbox>
<el-checkbox v-model="data.classTakeUnlimited" v-if="data.cover ==='2-3'|| data.cover=== '3-1'|| data.cover=== '3-2' ">添加带班班(无限制)</el-checkbox> <el-checkbox v-model="data.classTakeUnlimited" v-if="data.cover ==='2-3'|| data.cover=== '3-1'|| data.cover=== '3-2' || data.cover=== '3-6' || data.cover=== '3-7' ">添加带班班(无限制)</el-checkbox>
<el-checkbox v-model="data.distribution" v-if="data.cover ==='5-9'||data.cover ==='7-9'" @change="distribution">批量分配</el-checkbox> <el-checkbox v-model="data.distribution" v-if="data.cover ==='5-9'||data.cover ==='7-9'" @change="distribution">批量分配</el-checkbox>
<el-checkbox v-model="data.exportFinish" v-if="data.cover === '2-3'">导出完课用户</el-checkbox> <el-checkbox v-model="data.exportFinish" v-if="data.cover === '2-3'">导出完课用户</el-checkbox>
<el-checkbox v-model="data.import" v-if="data.cover ==='6-3'||data.cover ==='5-3'||data.cover ==='5-9'">导入</el-checkbox> <el-checkbox v-model="data.import" v-if="data.cover ==='6-3'||data.cover ==='5-3'||data.cover ==='5-9'||data.cover ==='6-4'">导入</el-checkbox>
<el-checkbox v-model="data.export" v-if="exportMenuList.indexOf(data.cover) >-1">导出</el-checkbox> <el-checkbox v-model="data.export" v-if="exportMenuList.indexOf(data.cover) >-1">导出</el-checkbox>
<el-checkbox v-model="data.readonly">只读</el-checkbox> <el-checkbox v-model="data.readonly">只读</el-checkbox>
<el-checkbox v-model="data.delete">删除</el-checkbox> <el-checkbox v-model="data.delete">删除</el-checkbox>
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
limit: 10, limit: 10,
roleList: [], roleList: [],
exportMenuList: [ // 导出权限 exportMenuList: [ // 导出权限
'2-3', '5-10', '5-2', '5-1', '5-3', '5-8', '5-9', '6-4', '3-1', '7-9', '6-3', '10-8' '2-3', '5-10', '5-2', '5-1', '5-3', '5-8', '5-9', '6-4', '3-1', '3-6', '3-7', '7-9', '6-3', '10-8'
], ],
dialog: { dialog: {
title: '新增角色', title: '新增角色',
...@@ -128,9 +128,10 @@ ...@@ -128,9 +128,10 @@
j.delete = false; j.delete = false;
if (this.exportMenuList.indexOf(j.cover) > -1) j.export = false; if (this.exportMenuList.indexOf(j.cover) > -1) j.export = false;
if (j.cover === "5-9" || j.cover === "7-9") j.distribution = false; if (j.cover === "5-9" || j.cover === "7-9") j.distribution = false;
if (j.cover === "6-3" || j.cover === "5-3" || j.cover === "5-9") j.import = false; if (j.cover === "6-3" || j.cover === "5-3" || j.cover === "5-9"|| j.cover === "6-4") j.import = false;
if (j.name === '月课订单列表' || j.name === '日课订单列表' || j.name === "来源码管理" || j.cover === "5-9" || j.cover === "2-3" || j.cover === "3-1" || j.cover === '3-2') j.refund = false; if (j.name === '月课订单列表' || j.name === '日课订单列表' || j.name === "来源码管理"
if (j.cover === "2-3" || j.cover === "3-1" || j.cover === '3-2') { || j.cover === "5-9" || j.cover === "2-3" || j.cover === "3-1" || j.cover === '3-2' || j.cover === "3-6" || j.cover === "3-7") j.refund = false;
if (j.cover === "2-3" || j.cover === "3-1" || j.cover === '3-2' || j.cover === "3-6" || j.cover === "3-7") {
j.classManageUnlimited = false; j.classManageUnlimited = false;
j.classManage = false; j.classManage = false;
j.classTakeUnlimited = false; j.classTakeUnlimited = false;
...@@ -178,9 +179,10 @@ ...@@ -178,9 +179,10 @@
j.delete = false; j.delete = false;
if (this.exportMenuList.indexOf(j.cover) > -1) j.export = false; if (this.exportMenuList.indexOf(j.cover) > -1) j.export = false;
if (j.cover === "5-9" || j.cover === "7-9") j.distribution = false; if (j.cover === "5-9" || j.cover === "7-9") j.distribution = false;
if (j.cover === "6-3" || j.cover === "5-3" || j.cover === "5-9") j.import = false; if (j.cover === "6-3" || j.cover === "5-3" || j.cover === "5-9"|| j.cover === "6-4") j.import = false;
if (j.name === '月课订单列表' || j.name === '日课订单列表' || j.name === "来源码管理" || j.cover === "5-9" || j.cover === "2-3" || j.cover === "3-1" || j.cover === '3-2') j.refund = false; if (j.name === '月课订单列表' || j.name === '日课订单列表' || j.name === "来源码管理"
if (j.cover === "2-3" || j.cover === "3-1" || j.cover === '3-2') { || j.cover === "5-9" || j.cover === "2-3" || j.cover === "3-1" || j.cover === '3-2' || j.cover === "3-6" || j.cover === "3-7") j.refund = false;
if (j.cover === "2-3" || j.cover === "3-1" || j.cover === '3-2' || j.cover === "3-6" || j.cover === "3-7") {
j.classManageUnlimited = false; j.classManageUnlimited = false;
j.classManage = false; j.classManage = false;
j.classTakeUnlimited = false; j.classTakeUnlimited = false;
...@@ -208,15 +210,16 @@ ...@@ -208,15 +210,16 @@
x.readonly = !!i.readonly; x.readonly = !!i.readonly;
x.delete = !!i.delete; x.delete = !!i.delete;
if (this.exportMenuList.indexOf(i.cover) > -1) x.export = !!i.export; if (this.exportMenuList.indexOf(i.cover) > -1) x.export = !!i.export;
if (i.cover === '5-1' || i.cover === '5-10' || i.cover === "10-1" || i.cover === "5-9" || i.cover === "2-3" || i.cover === "3-1" || i.cover === '3-2') { if (i.cover === '5-1' || i.cover === '5-10' || i.cover === "10-1" || i.cover === "5-9" || i.cover === "2-3"
|| i.cover === "3-1" || i.cover === '3-2' || i.cover === "3-6" || i.cover === "3-7") {
x.refund = !!i.refund; x.refund = !!i.refund;
} }
if (i.cover === "2-3" || i.cover === "3-1" || i.cover === '3-2') { if (i.cover === "2-3" || i.cover === "3-1" || i.cover === '3-2' || i.cover === "3-6" || i.cover === "3-7") {
x.classManage = !!i.classManage; x.classManage = !!i.classManage;
x.classManageUnlimited = !!i.classManageUnlimited; x.classManageUnlimited = !!i.classManageUnlimited;
x.classTakeUnlimited = !!i.classTakeUnlimited; x.classTakeUnlimited = !!i.classTakeUnlimited;
} }
if (i.cover === "6-3" || i.cover === "5-3" || i.cover === "5-9") { if (i.cover === "6-3" || i.cover === "5-3" || i.cover === "5-9"|| i.cover === "6-4") {
x.import = !!i.import; x.import = !!i.import;
} }
if (i.cover === "5-9" || i.cover === "7-9") { if (i.cover === "5-9" || i.cover === "7-9") {
......
...@@ -38,8 +38,7 @@ ...@@ -38,8 +38,7 @@
<span v-if="type===1">{{teacherDetail.status}}</span> <span v-if="type===1">{{teacherDetail.status}}</span>
<el-form-item v-if="type !== 1"> <el-form-item v-if="type !== 1">
<el-select v-model="form.status" placeholder="请选择"> <el-select v-model="form.status" placeholder="请选择">
<el-option v-for="data in statusOption" :key="data.value" :label="data.label" <el-option v-for="data in statusOption" :key="data.value" :label="data.label" :value="data.value"></el-option>
:value="data.value"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
...@@ -47,9 +46,9 @@ ...@@ -47,9 +46,9 @@
<el-col :span="8"> <el-col :span="8">
<span v-if="type===1">{{teacherDetail.type}}</span> <span v-if="type===1">{{teacherDetail.type}}</span>
<el-form-item v-if="type !== 1"> <el-form-item v-if="type !== 1">
<el-select v-model="form.type" placeholder="请选择"> <!--<el-select v-model="form.type" placeholder="请选择" disabled>-->
<el-option v-for="data in dialogObj.teacherTypeList" :key="data.type" :label="data.name" <el-select v-model="form.type" placeholder="请选择" :disabled="typeList.length < 2">
:value="data.type"></el-option> <el-option v-for="data in typeList" :key="data.type" :label="data.name" :value="data.type"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
...@@ -141,6 +140,7 @@ ...@@ -141,6 +140,7 @@
], ],
loading:true, loading:true,
type:0, type:0,
typeList: [],
title:'', title:'',
form:{ form:{
name:'', name:'',
...@@ -167,7 +167,7 @@ ...@@ -167,7 +167,7 @@
methods:{ methods:{
sub(){ sub(){
if(this.imageList.length > 0){ if(this.imageList.length > 0){
this.form.qr = this.imageList[0].url; this.form.qr = this.imageList[0].url;
} }
let json = { let json = {
name:this.form.name, name:this.form.name,
...@@ -181,16 +181,16 @@ ...@@ -181,16 +181,16 @@
switch(this.dialogObj.type){ switch(this.dialogObj.type){
case 2: case 2:
this.$refs['form'].validate((valid) => { this.$refs['form'].validate((valid) => {
if(valid){ if (valid) {
editTeacherApi(this.id,json).then(res=>{ editTeacherApi(this.id, json).then(res => {
this.$message({ this.$message({
type: 'success', type: 'success',
message: '修改成功!' message: '修改成功!'
}); });
this.$emit("reflash"); this.$emit("reflash");
this.show = false; this.show = false;
}) })
} }
}); });
break; break;
case 0: case 0:
...@@ -235,41 +235,63 @@ ...@@ -235,41 +235,63 @@
this.loading = false; this.loading = false;
}) })
}, },
initType() {
// debugger
if (this.dialogObj.teacherTypeList && this.dialogObj.teacherTypeList.length) {
if (String(this.dialogObj.typeAdd).indexOf(',') > -1) { // 3,4
let typeAddArr = this.dialogObj.typeAdd.split(','), arr = [];
typeAddArr.forEach(val => {
let idx = this.dialogObj.teacherTypeList.findIndex(i => i.type == val);
if (idx > -1) {
arr.push(this.dialogObj.teacherTypeList[idx])
}
})
this.typeList = arr;
} else if (this.dialogObj.typeAdd == 0 || this.dialogObj.typeAdd == 2) {
let idx = this.dialogObj.teacherTypeList.findIndex(i => i.type == this.dialogObj.typeAdd);
if (idx > -1) {
this.typeList = [this.dialogObj.teacherTypeList[idx]]
}
}
}
},
initDialog(){ initDialog(){
console.log(this.dialogObj) // console.log(this.dialogObj)
this.initType();
switch(this.dialogObj.type){ switch(this.dialogObj.type){
case 0: case 0: // 添加
this.title = '新增教师'; this.title = '新增';
this.show = this.dialogObj.show; this.show = this.dialogObj.show;
this.type = 0; this.type = 0;
this.form.name = ""; this.form.name = "";
this.form.alias = ""; this.form.alias = "";
this.form.qr = ""; this.form.qr = "";
this.form.squad = ""; this.form.squad = "";
this.form.type = 0; this.form.type = String(this.dialogObj.typeAdd).indexOf(',')>-1 ? 3 : this.dialogObj.typeAdd;
this.form.status = 0; this.form.status = 0;
this.imageList = []; this.imageList = [];
this.loading = false; this.loading = false;
this.uploadShow = true; this.uploadShow = true;
this.form.media_id = ''; this.form.media_id = '';
break; break;
case 1: case 1: // 查看
this.title = '教师详情'; this.title = '详情';
this.show = this.dialogObj.show; this.show = this.dialogObj.show;
this.id = this.dialogObj.id; this.id = this.dialogObj.id;
this.type = 1; this.type = 1;
getTeacherDetailApi(this.id).then(res=>{ getTeacherDetailApi(this.id).then(res => {
this.teacherDetail = res; this.teacherDetail = res;
this.loading = false this.loading = false
}); });
break; break;
case 2: case 2: // 编辑
this.title = '编辑'; this.title = '编辑';
this.show = this.dialogObj.show; this.show = this.dialogObj.show;
this.id = this.dialogObj.id; this.id = this.dialogObj.id;
this.type = 2; this.type = 2;
getTeacherDetailApi(this.id).then(res=>{ getTeacherDetailApi(this.id).then(res => {
this.form.name = res.name; this.form.name = res.name;
this.form.squad = res.squad; this.form.squad = res.squad;
this.form.alias = res.alias; this.form.alias = res.alias;
...@@ -277,7 +299,7 @@ ...@@ -277,7 +299,7 @@
this.form.type = res.type; this.form.type = res.type;
this.form.status = res.status; this.form.status = res.status;
this.form.media_id = res.media_id ? res.media_id : ''; this.form.media_id = res.media_id ? res.media_id : '';
this.imageList = [{name:res.qr,url:res.qr}]; this.imageList = [{name: res.qr, url: res.qr}];
this.uploadShow = !res.qr; this.uploadShow = !res.qr;
this.loading = false; this.loading = false;
}); });
...@@ -287,6 +309,10 @@ ...@@ -287,6 +309,10 @@
} }
}, },
watch:{ watch:{
'dialogObj.teacherTypeList'() {
console.log('listUpdate'); // todo 似乎无用?
this.initType();
},
dialogObj:{ dialogObj:{
handler: function () { handler: function () {
this.loading = true; this.loading = true;
......
<template>
<div class="user">
<el-form ref="searchFrom" :model="searchFrom" size="mini" label-width="68px" inline>
<el-form-item label="昵称">
<el-input v-model="searchFrom.name" style="width: 90px"></el-input>
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="searchFrom.alias" style="width: 110px"></el-input>
</el-form-item>
<el-form-item label="老师状态" clearable>
<el-select v-model="searchFrom.status" @change="getUser" style="width: 88px" clearable>
<el-option label="带班" value="0"></el-option>
<el-option label="不带班" value="1"></el-option>
</el-select>
</el-form-item>
<!--<el-form-item label="教师类型">
<el-select v-model="searchFrom.type" style="width: 95px" placeholder="请选择" @change="getUser" clearable>
&lt;!&ndash; <el-option
v-for="item in dialogObj.teacherTypeList"
:key="item.id"
:label="item.label"
:value="item.id">
</el-option> &ndash;&gt;
<el-option v-for="data in dialogObj.teacherTypeList" :key="data.type" :label="data.name"
:value="data.type"></el-option>
</el-select>
</el-form-item>-->
<el-form-item label="任务日期">
<el-date-picker
style="width: 140px;"
type="date"
v-model="searchFrom.task_date"
value-format="yyyy-MM-dd"
placeholder="选择日期">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" plain @click="getUser">搜索</el-button>
</el-form-item>
<!--<el-form-item v-if="$store.state.orderRefund">-->
<!--<el-button type="success" plain @click="add">新增教师</el-button>-->
<el-form-item v-if="!$store.state.readonly">
<el-button type="success" plain @click="add">新增增长运营</el-button>
</el-form-item>
</el-form>
<el-tabs v-model="searchFrom.squad" type="card" style="background: white;padding-top: 10px" @tab-click="getUser">
<el-tab-pane v-if="phoneNumObj.teacher_type!='teacher_leader'" v-for="i in 10" :key="i" :label="'T'+i" :name="i.toString()"/>
<!-- <el-tab-pane v-if="phoneNumObj.teacher_type=='teacher_leader'" :key="phoneNumObj.squad" :label="'T'+phoneNumObj.squad" :name="phoneNumObj.squad.toString()"/> -->
</el-tabs>
<el-table
size="mini"
:data="userList"
height="calc(100vh - 335px)"
style="width: 100%">
<el-table-column
prop="name"
width="250"
label="老师">
<template slot-scope="scope">
<div style="display: flex;">
<a :href="scope.row.qr" target="_blank" class="clearfix">
<img class="avatar" :src="scope.row.qr" alt="二维码">
</a>
<div>
老师名:{{scope.row.name}}
<br>
微信号:{{scope.row.alias}}
<br>
类别:{{scope.row.type | teacherType}}
<br>
顾问:{{scope.row.adviser}}
<br>
开始时间:<span style="display: inline-block;width: 72px;vertical-align: text-top;line-height: 16px;">{{scope.row.teacher_start}}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column
prop="name"
label="添加好友">
<template slot-scope="scope">
进班人数:{{scope.row.into_class_num}}<br>
加老师处理数:{{scope.row.add_teacher_exec_num}}<br>
加老师成功数:{{scope.row.add_teacher_success_num}}<br>
成功率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
:color="Number(scope.row.add_teacher_success_rate)>70 ? '#67C23A' : '#f00'"
:percentage="Number(scope.row.add_teacher_success_rate)?Number(scope.row.add_teacher_success_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
:color="Number(scope.row.add_teacher_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(scope.row.add_teacher_exec_rate)?Number(scope.row.add_teacher_exec_rate):0">
</el-progress>
</template>
</el-table-column>
<el-table-column
prop="name"
label="召回率">
<template slot-scope="scope">
需召回人数:{{scope.row.need_recall_num}}<br>
已沟通人数:{{scope.row.recall_desc_exec_num}}<br>
用户回复数:{{scope.row.recall_desc_reply_num}}<br>
达标率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
:color="Number(scope.row.recall_watch_rate)===100 ? '#67C23A' : '#dd001b'"
:percentage="Number(scope.row.recall_watch_rate)?Number(scope.row.recall_watch_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
:color="Number(scope.row.recall_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(scope.row.recall_exec_rate)?Number(scope.row.recall_exec_rate):0">
</el-progress>
</template>
</el-table-column>
<el-table-column
prop="name"
label="意向标记">
<template slot-scope="scope">
意向用户数:{{scope.row.intention_num}}<br>
完课沟通用户数{{scope.row.over_desc_exec_num}}<br>
往期活跃用户沟通数:{{scope.row.past_desc_exec_num}}<br>
标记率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
color="#67C23A"
:percentage="Number(scope.row.over_intention_rate)?Number(scope.row.over_intention_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
:color="Number(scope.row.over_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(scope.row.over_exec_rate)?Number(scope.row.over_exec_rate):0">
</el-progress>
</template>
</el-table-column>
<el-table-column
prop="intention_num"
width="100"
label="意向用户数">
</el-table-column>
<el-table-column
prop="performance"
width="100"
label="当月业绩">
</el-table-column>
<el-table-column width="320" label="操作">
<template slot-scope="scope">
<el-button size="mini" plain type="primary" @click="goToTeacherDetail(scope.row)">查看详情</el-button>
<el-button size="mini" plain type="warning" @click="edit(scope.row)" v-if="!$store.state.readonly">编辑</el-button>
<el-button size="mini" plain type="success" @click="transferToggle(scope.row)" v-if="!$store.state.readonly">移交</el-button>
<el-button size="mini" plain type="danger" @click="delTeacher(scope.row)" v-if="$store.state.deletePermission && !$store.state.readonly">删除</el-button>
</template>
</el-table-column>
</el-table>
<div v-if="res" class="total-tab">
<div>总计</div>
<div>
<div>
成功率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
:color="Number(res.add_teacher_success_rate)>70 ? '#67C23A' : '#f00'"
:percentage="Number(res.add_teacher_success_rate)?Number(res.add_teacher_success_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
:color="Number(res.add_teacher_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(res.add_teacher_exec_rate)?Number(res.add_teacher_exec_rate):0">
</el-progress>
</div>
</div>
<div>
<div>
达标率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
:color="Number(res.recall_watch_rate)===100 ? '#67C23A' : '#ff0000'"
:percentage="Number(res.recall_watch_rate)?Number(res.recall_watch_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
:color="Number(res.recall_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(res.recall_exec_rate)?Number(res.recall_exec_rate):0">
</el-progress>
</div>
</div>
<div>
<div>
标记率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
color="#67C23A"
:percentage="Number(res.over_intention_rate)?Number(res.over_intention_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
:color="Number(res.over_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(res.over_exec_rate)?Number(res.over_exec_rate):0">
</el-progress>
</div>
</div>
<div>
{{res.intention_num}}
</div>
<div>
{{res.total_money}}
</div>
<div></div>
</div>
<page :total="total" :limit="limit" @pageChange="onPageChange" @sizeChange="onSizeChange"/>
<dialog-com :dialogObj="dialogObj" @changeShow="changeShow" @reflash="getUser"/>
<el-dialog width="90%" top="5vh" :visible.sync="dialogDetail.show">
<div v-if="dialogDetail.show">
<teacher-detail :parentDetail="dialogDetail"></teacher-detail>
</div>
</el-dialog>
<el-dialog width="500px" :visible.sync="transfer.show" title="移交">
<el-form ref="transferForm" :rules="transfer.form.rules" :model="transfer.form" label-width="100px">
<el-form-item label="当前设备:" prop="teacher_name">
{{transfer.form.teacher_name}}
</el-form-item>
<el-form-item label="当前顾问:" prop="staff_current_name">
{{transfer.form.staff_current_name}}
</el-form-item>
<el-form-item label="移交顾问:" prop="staff_id">
<el-select v-model="transfer.form.staff_id" filterable placeholder="请选择" :clearable="false" @change="transferStaffName">
<el-option
v-for="(data,index) in transfer.staff"
:key="index"
:label="data.name"
:value="data.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="移交时间:" prop="transfer_at">
<div style="display: flex;">
<el-date-picker
v-model="transfer.form.transfer_at" :clearable="false" value-format="yyyy-MM-dd HH:mm:ss"
type="datetime" placeholder="选择时间"></el-date-picker>
</div>
</el-form-item>
<el-form-item label="移交原因:" prop="reason">
<el-select v-model="transfer.form.reason" filterable placeholder="请选择" :clearable="false" @change="transferReasonName">
<el-option
v-for="(data,index) in transfer.reasonList"
:key="index"
:label="data.name"
:value="data.id">
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="transferToggle">取消</el-button>
<el-button type="primary" @click="transferSave">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {getTeacherListApi,delTeacherApi,getStaffListApi,postTransferTeacherApi,getTeacherTypeListApi} from "../../service/api";
import {TEACHERTYPE} from "../../util/wordbook";
import page from '../framework/page'
import teacherDetail from '../teacherDetail/index'
import dialogCom from './dialog'
// import Dialog from "../class/dialog";
let teacherTypeSource = {}
export default {
name: "growth",
data(){
let nowDate = this.formatTime(new Date());
return {
transfer: {
show: false,
form: {
reason: '',
reason_name: '',
teacher_name: '',
teacher_id: '',
staff_current_name: '', // 当前顾问名
staff_name: '', // 移交顾问name
staff_id: '', // 移交顾问id
transfer_at: '',
rules: {
staff_id: [{required: true, message: '请选择', trigger: 'change'}],
transfer_at: [{required: true, message: '请选择', trigger: 'change'}],
reason: [{required: true, message: '请选择', trigger: 'change'}],
},
},
staff: [0],
reasonList: [{
id: 0,
name: '人员入职',
},{
id: 1,
name: '人员离职',
},{
id: 2,
name: '请假',
},{
id: 3,
name: '其它',
},]
},
searchFrom:{
name:'',
alias:"",
status:'0',
task_date:nowDate,
squad:"1",
type: '3,4', // 3、4 增长运营 tmk
},
dialogObj:{
typeAdd: '3,4', // 与searchFrom.type一致
type:0,
show:false,
id:''
},
dialogDetail:{
show:false,
id:''
},
userList:[],
total:0,
nowPage:1,
limit: 20,
res:null,
dialogDetailObj:{
show:false,
title:'班级列表',
id: ''
},
teacherTypeOption: [{
id: 0,
label: '老师'
}, {
id: 1,
label: '新星妈妈'
}],
phoneNumObj:{}
}
},
watch:{
'dialogDetail.show'(value){
if(!value){
this.getUser()
}
}
},
components:{
// Dialog,
page,
dialogCom,
teacherDetail
},
filters:{
teacherType(value){
return teacherTypeSource[value]
}
},
mounted(){
// console.log(s)
let data = localStorage.getItem("phoneNum");
console.log(data)
// debugger
if(data){
data = JSON.parse(data)
this.phoneNumObj=data;
}
if(data&&data.teacher_type!='teacher_leader'){
this.$router.push('/teacher/'+ data.id);
}else{
this.getUser()
}
getTeacherTypeListApi().then(res=>{
this.dialogObj.teacherTypeList = res
let obj = {}
res.forEach((item,index)=>{
obj[item.type]=item.name
})
teacherTypeSource = obj
console.log(obj)
});
},
methods:{
onPageChange(val){
this.nowPage = val;
this.getUser()
},
formatTime(date){
let year = date.getFullYear();
let Month = date.getMonth()+1;
if(Month < 10){
Month = `0${Month}`
}
let Day = date.getDate();
if(Day<10)Day = `0${Day}`;
return `${year}-${Month}-${Day}`;
},
onSizeChange(val){
this.limit = val
this.nowPage = 1;
this.getUser()
},
getUser(){
let json = {
limit: this.limit,
page: this.nowPage
}
if (this.searchFrom.type || this.searchFrom.type === 0) {
json.type = this.searchFrom.type
}
if (this.searchFrom.status){
json.status = this.searchFrom.status
}
if (this.searchFrom.name) {
json.name = this.searchFrom.name
}
if (this.searchFrom.alias) {
json.alias = this.searchFrom.alias
}
if (this.searchFrom.task_date){
json.task_date = this.searchFrom.task_date
}
let data = localStorage.getItem("phoneNum");
if(data){
data = JSON.parse(data)
}
if(data&&data.teacher_type=='teacher_leader'){
json.squad = data.squad
}else{
json.squad = this.searchFrom.squad
}
getTeacherListApi(json).then(res=>{
this.userList = res.list;
this.total = res.total;
this.res=res;
})
},
transferStaffName(data) {
this.transfer.form.staff_name = this.transfer.staff.find(x => x.id == data).name;
},
transferReasonName(data) {
this.transfer.form.reason_name = this.transfer.reasonList.find(x => x.id == data).name;
},
transferToggle(data) {
this.transfer.show = !this.transfer.show;
if (this.transfer.show){
if (this.transfer.staff[0] === 0) {
let json = { limit: 1000, page: 1, status: 0 }; // status 0 在职
getStaffListApi(json).then(res => {
this.transfer.staff = res.list;
});
}
this.$nextTick(()=>{
this.$refs['transferForm'].resetFields();
this.transfer.form.teacher_name = data.name;
this.transfer.form.teacher_id = data.id;
this.transfer.form.staff_current_name = data.adviser;
})
} else {
this.$nextTick(()=>{
this.$refs['transferForm'].resetFields();
})
}
},
transferSave() {
this.$refs['transferForm'].validate((valid) => {
if (valid) {
this.$confirm(`确定将
<span style="color: red;">${this.transfer.form.teacher_name}</span> 移交给
<span style="color: red;">${this.transfer.form.staff_name}</span> ?<br>
移交开始时间 ${this.transfer.form.transfer_at} <br>
移交原因 ${this.transfer.form.reason_name}`, '提示', {
dangerouslyUseHTMLString: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var json = {
teacher_id: this.transfer.form.teacher_id,
staff_id: this.transfer.form.staff_id,
transfer_at: this.transfer.form.transfer_at,
reason: this.transfer.form.reason,
};
postTransferTeacherApi(json).then(res => {
this.$message({type: 'success', message: '移交成功!'});
this.transferToggle();
this.getUser();
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消移交'
});
});
} else {
console.log('error submit!!');
return false;
}
});
},
edit(data){
this.dialogObj.id = data.id;
this.dialogObj.type = 2;
this.dialogObj.show = true
},
add(){
this.dialogObj.type = 0;
this.dialogObj.show = true
},
detail(data){
this.dialogObj.id = data.id;
this.dialogObj.type = 1;
this.dialogObj.show = true
},
delTeacher(data){
this.$confirm('此操作将删除该账号?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delTeacherApi(data.id).then(res=>{
this.$message({
type: 'success',
message: '删除成功!'
});
this.getUser()
});
});
},
changeShow(data){
this.dialogObj.show=data
},
classDetail(row){
this.dialogDetailObj = {
show:true,
title:row.name + '班级详情',
id: row.id
}
},
goToTeacherDetail(row){
// this.$router.push('/teacher/'+ row.id);
this.dialogDetail.id = row.id;
this.dialogDetail.alias = row.alias;
this.dialogDetail.name = row.name;
this.dialogDetail.adviser = row.adviser;
this.dialogDetail.show = true
}
}
}
</script>
<style scoped lang="less">
@import "../../util/public";
.user{
/*height: 100%;*/
overflow: auto;
padding: 20px 0;
.btn-content{
text-align: center;
}
}
/deep/.el-progress-bar__outer{
background: #cccccc;
}
.total-tab{
display: table;
background: #dfedff;
width: 100%;
vertical-align: middle;
font-size: 12px;
&>div{
display: table-cell;
vertical-align: middle;
padding: 10px;
}
&>div:nth-child(1){
width: 230px;
min-width: 230px;
text-align: center;
}
&>div:nth-child(5){
min-width: 80px;
width: 80px;
}
&>div:nth-child(7){
min-width: 320px + 12px;
width: 320px + 12px;
}
&>div:nth-child(2),
&>div:nth-child(3),
&>div:nth-child(4){
min-width: 60px;
}
}
.avatar{
width: 70px;
margin-right: 5px;
height: 70px;
float: left;
}
.shortcut {
width: 50px;
}
</style>
...@@ -13,18 +13,18 @@ ...@@ -13,18 +13,18 @@
<el-option label="不带班" value="1"></el-option> <el-option label="不带班" value="1"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="教师类型"> <!--<el-form-item label="教师类型">
<el-select v-model="searchFrom.type" style="width: 95px" placeholder="请选择" @change="getUser" clearable> <el-select v-model="searchFrom.type" style="width: 95px" placeholder="请选择" @change="getUser" clearable>
<!-- <el-option &lt;!&ndash; <el-option
v-for="item in dialogObj.teacherTypeList" v-for="item in dialogObj.teacherTypeList"
:key="item.id" :key="item.id"
:label="item.label" :label="item.label"
:value="item.id"> :value="item.id">
</el-option> --> </el-option> &ndash;&gt;
<el-option v-for="data in dialogObj.teacherTypeList" :key="data.type" :label="data.name" <el-option v-for="data in dialogObj.teacherTypeList" :key="data.type" :label="data.name"
:value="data.type"></el-option> :value="data.type"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>-->
<el-form-item label="任务日期"> <el-form-item label="任务日期">
<el-date-picker <el-date-picker
style="width: 140px;" style="width: 140px;"
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
<el-form-item> <el-form-item>
<el-button type="primary" plain @click="getUser">搜索</el-button> <el-button type="primary" plain @click="getUser">搜索</el-button>
</el-form-item> </el-form-item>
<el-form-item v-if="$store.state.orderRefund"> <el-form-item v-if="!$store.state.readonly">
<el-button type="success" plain @click="add">新增教师</el-button> <el-button type="success" plain @click="add">新增教师</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -151,9 +151,9 @@ ...@@ -151,9 +151,9 @@
label="意向用户数"> label="意向用户数">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="performance" prop="performance"
width="100" width="100"
label="当月业绩"> label="当月业绩">
</el-table-column> </el-table-column>
<el-table-column width="320" label="操作"> <el-table-column width="320" label="操作">
<template slot-scope="scope"> <template slot-scope="scope">
...@@ -187,40 +187,40 @@ ...@@ -187,40 +187,40 @@
</div> </div>
<div> <div>
<div> <div>
达标率:<el-progress 达标率:<el-progress
style="display: inline-block;width: calc(90% - 50px)" style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true" :text-inside="true"
:stroke-width="16" :stroke-width="16"
:color="Number(res.recall_watch_rate)===100 ? '#67C23A' : '#ff0000'" :color="Number(res.recall_watch_rate)===100 ? '#67C23A' : '#ff0000'"
:percentage="Number(res.recall_watch_rate)?Number(res.recall_watch_rate):0"> :percentage="Number(res.recall_watch_rate)?Number(res.recall_watch_rate):0">
</el-progress> </el-progress>
<br> <br>
处理率:<el-progress 处理率:<el-progress
style="display: inline-block;;width: calc(90% - 50px)" style="display: inline-block;;width: calc(90% - 50px)"
:text-inside="true" :text-inside="true"
:stroke-width="16" :stroke-width="16"
:color="Number(res.recall_exec_rate)===100 ? '#67C23A' : '#f00'" :color="Number(res.recall_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(res.recall_exec_rate)?Number(res.recall_exec_rate):0"> :percentage="Number(res.recall_exec_rate)?Number(res.recall_exec_rate):0">
</el-progress> </el-progress>
</div> </div>
</div> </div>
<div> <div>
<div> <div>
标记率:<el-progress 标记率:<el-progress
style="display: inline-block;width: calc(90% - 50px)" style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true" :text-inside="true"
:stroke-width="16" :stroke-width="16"
color="#67C23A" color="#67C23A"
:percentage="Number(res.over_intention_rate)?Number(res.over_intention_rate):0"> :percentage="Number(res.over_intention_rate)?Number(res.over_intention_rate):0">
</el-progress> </el-progress>
<br> <br>
处理率:<el-progress 处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)" style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true" :text-inside="true"
:stroke-width="16" :stroke-width="16"
:color="Number(res.over_exec_rate)===100 ? '#67C23A' : '#f00'" :color="Number(res.over_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(res.over_exec_rate)?Number(res.over_exec_rate):0"> :percentage="Number(res.over_exec_rate)?Number(res.over_exec_rate):0">
</el-progress> </el-progress>
</div> </div>
</div> </div>
<div> <div>
...@@ -289,7 +289,7 @@ ...@@ -289,7 +289,7 @@
import page from '../framework/page' import page from '../framework/page'
import teacherDetail from '../teacherDetail/index' import teacherDetail from '../teacherDetail/index'
import dialogCom from './dialog' import dialogCom from './dialog'
import Dialog from "../class/dialog"; // import Dialog from "../class/dialog";
let teacherTypeSource = {} let teacherTypeSource = {}
export default { export default {
name: "index", name: "index",
...@@ -334,7 +334,13 @@ ...@@ -334,7 +334,13 @@
status:'0', status:'0',
task_date:nowDate, task_date:nowDate,
squad:"1", squad:"1",
type:"", type:0,
},
dialogObj:{
typeAdd: 0, // 与searchFrom.type一致
type:0,
show:false,
id:''
}, },
dialogDetail:{ dialogDetail:{
show:false, show:false,
...@@ -344,11 +350,6 @@ ...@@ -344,11 +350,6 @@
total:0, total:0,
nowPage:1, nowPage:1,
limit: 20, limit: 20,
dialogObj:{
type:0,
show:false,
id:''
},
res:null, res:null,
dialogDetailObj:{ dialogDetailObj:{
show:false, show:false,
...@@ -373,7 +374,7 @@ ...@@ -373,7 +374,7 @@
} }
}, },
components:{ components:{
Dialog, // Dialog,
page, page,
dialogCom, dialogCom,
teacherDetail teacherDetail
...@@ -384,7 +385,6 @@ ...@@ -384,7 +385,6 @@
} }
}, },
mounted(){ mounted(){
console.log(this.dialogDetail)
// console.log(s) // console.log(s)
let data = localStorage.getItem("phoneNum"); let data = localStorage.getItem("phoneNum");
console.log(data) console.log(data)
...@@ -596,7 +596,7 @@ ...@@ -596,7 +596,7 @@
background: #cccccc; background: #cccccc;
} }
.total-tab{ .total-tab{
display: table; display: table;
background: #dfedff; background: #dfedff;
width: 100%; width: 100%;
vertical-align: middle; vertical-align: middle;
......
<template>
<div class="user">
<el-form ref="searchFrom" :model="searchFrom" size="mini" label-width="68px" inline>
<el-form-item label="昵称">
<el-input v-model="searchFrom.name" style="width: 90px"></el-input>
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="searchFrom.alias" style="width: 110px"></el-input>
</el-form-item>
<el-form-item label="老师状态" clearable>
<el-select v-model="searchFrom.status" @change="getUser" style="width: 88px" clearable>
<el-option label="带班" value="0"></el-option>
<el-option label="不带班" value="1"></el-option>
</el-select>
</el-form-item>
<!--<el-form-item label="教师类型">
<el-select v-model="searchFrom.type" style="width: 95px" placeholder="请选择" @change="getUser" clearable>
&lt;!&ndash; <el-option
v-for="item in dialogObj.teacherTypeList"
:key="item.id"
:label="item.label"
:value="item.id">
</el-option> &ndash;&gt;
<el-option v-for="data in dialogObj.teacherTypeList" :key="data.type" :label="data.name"
:value="data.type"></el-option>
</el-select>
</el-form-item>-->
<el-form-item label="任务日期">
<el-date-picker
style="width: 140px;"
type="date"
v-model="searchFrom.task_date"
value-format="yyyy-MM-dd"
placeholder="选择日期">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" plain @click="getUser">搜索</el-button>
</el-form-item>
<!--<el-form-item v-if="$store.state.orderRefund">-->
<el-form-item v-if="!$store.state.readonly">
<el-button type="success" plain @click="add">新增用户服务</el-button>
</el-form-item>
</el-form>
<el-tabs v-model="searchFrom.squad" type="card" style="background: white;padding-top: 10px" @tab-click="getUser">
<el-tab-pane v-if="phoneNumObj.teacher_type!='teacher_leader'" v-for="i in 10" :key="i" :label="'T'+i" :name="i.toString()"/>
<!-- <el-tab-pane v-if="phoneNumObj.teacher_type=='teacher_leader'" :key="phoneNumObj.squad" :label="'T'+phoneNumObj.squad" :name="phoneNumObj.squad.toString()"/> -->
</el-tabs>
<el-table
size="mini"
:data="userList"
height="calc(100vh - 335px)"
style="width: 100%">
<el-table-column
prop="name"
width="250"
label="老师">
<template slot-scope="scope">
<div style="display: flex;">
<a :href="scope.row.qr" target="_blank" class="clearfix">
<img class="avatar" :src="scope.row.qr" alt="二维码">
</a>
<div>
老师名:{{scope.row.name}}
<br>
微信号:{{scope.row.alias}}
<br>
类别:{{scope.row.type | teacherType}}
<br>
顾问:{{scope.row.adviser}}
<br>
开始时间:<span style="display: inline-block;width: 72px;vertical-align: text-top;line-height: 16px;">{{scope.row.teacher_start}}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column
prop="name"
label="添加好友">
<template slot-scope="scope">
进班人数:{{scope.row.into_class_num}}<br>
加老师处理数:{{scope.row.add_teacher_exec_num}}<br>
加老师成功数:{{scope.row.add_teacher_success_num}}<br>
成功率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
:color="Number(scope.row.add_teacher_success_rate)>70 ? '#67C23A' : '#f00'"
:percentage="Number(scope.row.add_teacher_success_rate)?Number(scope.row.add_teacher_success_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
:color="Number(scope.row.add_teacher_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(scope.row.add_teacher_exec_rate)?Number(scope.row.add_teacher_exec_rate):0">
</el-progress>
</template>
</el-table-column>
<el-table-column
prop="name"
label="召回率">
<template slot-scope="scope">
需召回人数:{{scope.row.need_recall_num}}<br>
已沟通人数:{{scope.row.recall_desc_exec_num}}<br>
用户回复数:{{scope.row.recall_desc_reply_num}}<br>
达标率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
:color="Number(scope.row.recall_watch_rate)===100 ? '#67C23A' : '#dd001b'"
:percentage="Number(scope.row.recall_watch_rate)?Number(scope.row.recall_watch_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
:color="Number(scope.row.recall_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(scope.row.recall_exec_rate)?Number(scope.row.recall_exec_rate):0">
</el-progress>
</template>
</el-table-column>
<el-table-column
prop="name"
label="意向标记">
<template slot-scope="scope">
意向用户数:{{scope.row.intention_num}}<br>
完课沟通用户数{{scope.row.over_desc_exec_num}}<br>
往期活跃用户沟通数:{{scope.row.past_desc_exec_num}}<br>
标记率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
color="#67C23A"
:percentage="Number(scope.row.over_intention_rate)?Number(scope.row.over_intention_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="18"
:color="Number(scope.row.over_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(scope.row.over_exec_rate)?Number(scope.row.over_exec_rate):0">
</el-progress>
</template>
</el-table-column>
<el-table-column
prop="intention_num"
width="100"
label="意向用户数">
</el-table-column>
<el-table-column
prop="performance"
width="100"
label="当月业绩">
</el-table-column>
<el-table-column width="320" label="操作">
<template slot-scope="scope">
<el-button size="mini" plain type="primary" @click="goToTeacherDetail(scope.row)">查看详情</el-button>
<el-button size="mini" plain type="warning" @click="edit(scope.row)" v-if="!$store.state.readonly">编辑</el-button>
<el-button size="mini" plain type="success" @click="transferToggle(scope.row)" v-if="!$store.state.readonly">移交</el-button>
<el-button size="mini" plain type="danger" @click="delTeacher(scope.row)" v-if="$store.state.deletePermission && !$store.state.readonly">删除</el-button>
</template>
</el-table-column>
</el-table>
<div v-if="res" class="total-tab">
<div>总计</div>
<div>
<div>
成功率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
:color="Number(res.add_teacher_success_rate)>70 ? '#67C23A' : '#f00'"
:percentage="Number(res.add_teacher_success_rate)?Number(res.add_teacher_success_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
:color="Number(res.add_teacher_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(res.add_teacher_exec_rate)?Number(res.add_teacher_exec_rate):0">
</el-progress>
</div>
</div>
<div>
<div>
达标率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
:color="Number(res.recall_watch_rate)===100 ? '#67C23A' : '#ff0000'"
:percentage="Number(res.recall_watch_rate)?Number(res.recall_watch_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
:color="Number(res.recall_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(res.recall_exec_rate)?Number(res.recall_exec_rate):0">
</el-progress>
</div>
</div>
<div>
<div>
标记率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
color="#67C23A"
:percentage="Number(res.over_intention_rate)?Number(res.over_intention_rate):0">
</el-progress>
<br>
处理率:<el-progress
style="display: inline-block;width: calc(90% - 50px)"
:text-inside="true"
:stroke-width="16"
:color="Number(res.over_exec_rate)===100 ? '#67C23A' : '#f00'"
:percentage="Number(res.over_exec_rate)?Number(res.over_exec_rate):0">
</el-progress>
</div>
</div>
<div>
{{res.intention_num}}
</div>
<div>
{{res.total_money}}
</div>
<div></div>
</div>
<page :total="total" :limit="limit" @pageChange="onPageChange" @sizeChange="onSizeChange"/>
<dialog-com :dialogObj="dialogObj" @changeShow="changeShow" @reflash="getUser"/>
<el-dialog width="90%" top="5vh" :visible.sync="dialogDetail.show">
<div v-if="dialogDetail.show">
<teacher-detail :parentDetail="dialogDetail"></teacher-detail>
</div>
</el-dialog>
<el-dialog width="500px" :visible.sync="transfer.show" title="移交">
<el-form ref="transferForm" :rules="transfer.form.rules" :model="transfer.form" label-width="100px">
<el-form-item label="当前设备:" prop="teacher_name">
{{transfer.form.teacher_name}}
</el-form-item>
<el-form-item label="当前顾问:" prop="staff_current_name">
{{transfer.form.staff_current_name}}
</el-form-item>
<el-form-item label="移交顾问:" prop="staff_id">
<el-select v-model="transfer.form.staff_id" filterable placeholder="请选择" :clearable="false" @change="transferStaffName">
<el-option
v-for="(data,index) in transfer.staff"
:key="index"
:label="data.name"
:value="data.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="移交时间:" prop="transfer_at">
<div style="display: flex;">
<el-date-picker
v-model="transfer.form.transfer_at" :clearable="false" value-format="yyyy-MM-dd HH:mm:ss"
type="datetime" placeholder="选择时间"></el-date-picker>
</div>
</el-form-item>
<el-form-item label="移交原因:" prop="reason">
<el-select v-model="transfer.form.reason" filterable placeholder="请选择" :clearable="false" @change="transferReasonName">
<el-option
v-for="(data,index) in transfer.reasonList"
:key="index"
:label="data.name"
:value="data.id">
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="transferToggle">取消</el-button>
<el-button type="primary" @click="transferSave">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {getTeacherListApi,delTeacherApi,getStaffListApi,postTransferTeacherApi,getTeacherTypeListApi} from "../../service/api";
import {TEACHERTYPE} from "../../util/wordbook";
import page from '../framework/page'
import teacherDetail from '../teacherDetail/index'
import dialogCom from './dialog'
// import Dialog from "../class/dialog";
let teacherTypeSource = {}
export default {
name: "userservice",
data(){
let nowDate = this.formatTime(new Date());
return {
transfer: {
show: false,
form: {
reason: '',
reason_name: '',
teacher_name: '',
teacher_id: '',
staff_current_name: '', // 当前顾问名
staff_name: '', // 移交顾问name
staff_id: '', // 移交顾问id
transfer_at: '',
rules: {
staff_id: [{required: true, message: '请选择', trigger: 'change'}],
transfer_at: [{required: true, message: '请选择', trigger: 'change'}],
reason: [{required: true, message: '请选择', trigger: 'change'}],
},
},
staff: [0],
reasonList: [{
id: 0,
name: '人员入职',
},{
id: 1,
name: '人员离职',
},{
id: 2,
name: '请假',
},{
id: 3,
name: '其它',
},]
},
searchFrom:{
name:'',
alias:"",
status:'0',
task_date:nowDate,
squad:"1",
type:2,
},
dialogObj:{
typeAdd: 2, // 用户服务 与searchFrom.type一致
type:0,
show:false,
id:''
},
dialogDetail:{
show:false,
id:''
},
userList:[],
total:0,
nowPage:1,
limit: 20,
res:null,
dialogDetailObj:{
show:false,
title:'班级列表',
id: ''
},
teacherTypeOption: [{
id: 0,
label: '老师'
}, {
id: 1,
label: '新星妈妈'
}],
phoneNumObj:{}
}
},
watch:{
'dialogDetail.show'(value){
if(!value){
this.getUser()
}
}
},
components:{
// Dialog,
page,
dialogCom,
teacherDetail
},
filters:{
teacherType(value){
return teacherTypeSource[value]
}
},
mounted(){
// console.log(s)
let data = localStorage.getItem("phoneNum");
console.log(data)
// debugger
if(data){
data = JSON.parse(data)
this.phoneNumObj=data;
}
if(data&&data.teacher_type!='teacher_leader'){
this.$router.push('/teacher/'+ data.id);
}else{
this.getUser()
}
getTeacherTypeListApi().then(res=>{
this.dialogObj.teacherTypeList = res
let obj = {}
res.forEach((item,index)=>{
obj[item.type]=item.name
})
teacherTypeSource = obj
console.log(obj)
});
},
methods:{
onPageChange(val){
this.nowPage = val;
this.getUser()
},
formatTime(date){
let year = date.getFullYear();
let Month = date.getMonth()+1;
if(Month < 10){
Month = `0${Month}`
}
let Day = date.getDate();
if(Day<10)Day = `0${Day}`;
return `${year}-${Month}-${Day}`;
},
onSizeChange(val){
this.limit = val
this.nowPage = 1;
this.getUser()
},
getUser(){
let json = {
limit: this.limit,
page: this.nowPage
}
if (this.searchFrom.type || this.searchFrom.type === 0) {
json.type = this.searchFrom.type
}
if (this.searchFrom.status){
json.status = this.searchFrom.status
}
if (this.searchFrom.name) {
json.name = this.searchFrom.name
}
if (this.searchFrom.alias) {
json.alias = this.searchFrom.alias
}
if (this.searchFrom.task_date){
json.task_date = this.searchFrom.task_date
}
let data = localStorage.getItem("phoneNum");
if(data){
data = JSON.parse(data)
}
if(data&&data.teacher_type=='teacher_leader'){
json.squad = data.squad
}else{
json.squad = this.searchFrom.squad
}
getTeacherListApi(json).then(res=>{
this.userList = res.list;
this.total = res.total;
this.res=res;
})
},
transferStaffName(data) {
this.transfer.form.staff_name = this.transfer.staff.find(x => x.id == data).name;
},
transferReasonName(data) {
this.transfer.form.reason_name = this.transfer.reasonList.find(x => x.id == data).name;
},
transferToggle(data) {
this.transfer.show = !this.transfer.show;
if (this.transfer.show){
if (this.transfer.staff[0] === 0) {
let json = { limit: 1000, page: 1, status: 0 }; // status 0 在职
getStaffListApi(json).then(res => {
this.transfer.staff = res.list;
});
}
this.$nextTick(()=>{
this.$refs['transferForm'].resetFields();
this.transfer.form.teacher_name = data.name;
this.transfer.form.teacher_id = data.id;
this.transfer.form.staff_current_name = data.adviser;
})
} else {
this.$nextTick(()=>{
this.$refs['transferForm'].resetFields();
})
}
},
transferSave() {
this.$refs['transferForm'].validate((valid) => {
if (valid) {
this.$confirm(`确定将
<span style="color: red;">${this.transfer.form.teacher_name}</span> 移交给
<span style="color: red;">${this.transfer.form.staff_name}</span> ?<br>
移交开始时间 ${this.transfer.form.transfer_at} <br>
移交原因 ${this.transfer.form.reason_name}`, '提示', {
dangerouslyUseHTMLString: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var json = {
teacher_id: this.transfer.form.teacher_id,
staff_id: this.transfer.form.staff_id,
transfer_at: this.transfer.form.transfer_at,
reason: this.transfer.form.reason,
};
postTransferTeacherApi(json).then(res => {
this.$message({type: 'success', message: '移交成功!'});
this.transferToggle();
this.getUser();
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消移交'
});
});
} else {
console.log('error submit!!');
return false;
}
});
},
edit(data){
this.dialogObj.id = data.id;
this.dialogObj.type = 2;
this.dialogObj.show = true
},
add(){
this.dialogObj.type = 0;
this.dialogObj.show = true
},
detail(data){
this.dialogObj.id = data.id;
this.dialogObj.type = 1;
this.dialogObj.show = true
},
delTeacher(data){
this.$confirm('此操作将删除该账号?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delTeacherApi(data.id).then(res=>{
this.$message({
type: 'success',
message: '删除成功!'
});
this.getUser()
});
});
},
changeShow(data){
this.dialogObj.show=data
},
classDetail(row){
this.dialogDetailObj = {
show:true,
title:row.name + '班级详情',
id: row.id
}
},
goToTeacherDetail(row){
// this.$router.push('/teacher/'+ row.id);
this.dialogDetail.id = row.id;
this.dialogDetail.alias = row.alias;
this.dialogDetail.name = row.name;
this.dialogDetail.adviser = row.adviser;
this.dialogDetail.show = true
}
}
}
</script>
<style scoped lang="less">
@import "../../util/public";
.user{
/*height: 100%;*/
overflow: auto;
padding: 20px 0;
.btn-content{
text-align: center;
}
}
/deep/.el-progress-bar__outer{
background: #cccccc;
}
.total-tab{
display: table;
background: #dfedff;
width: 100%;
vertical-align: middle;
font-size: 12px;
&>div{
display: table-cell;
vertical-align: middle;
padding: 10px;
}
&>div:nth-child(1){
width: 230px;
min-width: 230px;
text-align: center;
}
&>div:nth-child(5){
min-width: 80px;
width: 80px;
}
&>div:nth-child(7){
min-width: 320px + 12px;
width: 320px + 12px;
}
&>div:nth-child(2),
&>div:nth-child(3),
&>div:nth-child(4){
min-width: 60px;
}
}
.avatar{
width: 70px;
margin-right: 5px;
height: 70px;
float: left;
}
.shortcut {
width: 50px;
}
</style>
<template>
<el-dialog :title="title" append-to-body :visible.sync="show" width="960px">
<div v-loading="loading">
<!--回访 开始-->
<el-table v-if="dialogObj.type == 'callback'" :data="list" border size="small">
<el-table-column label="销售顾问" prop="staff_name"></el-table-column>
<el-table-column label="老师名" prop="teacher_name"></el-table-column>
<el-table-column label="UID" prop="user_id"></el-table-column>
<el-table-column label="客户微信昵称" prop="nickname"></el-table-column>
<el-table-column label="电话号码">
<template slot-scope="scope">{{scope.row.mobile || '-'}}</template>
</el-table-column>
<el-table-column label="意向度">
<template slot-scope="scope">{{scope.row.intention || '-'}}</template>
</el-table-column>
<el-table-column label="最近备注时间">
<template slot-scope="scope">
<template v-if="scope.row.remark_time && String(scope.row.remark_time).indexOf(' ') > -1">
<div>{{String(scope.row.remark_time).split(' ')[0]}}</div>
<div>{{String(scope.row.remark_time).split(' ')[1]}}</div>
</template>
<template v-else>-</template>
</template>
</el-table-column>
<el-table-column label="下次回访时间">
<template slot-scope="scope">{{scope.row.next_visit_at || '-'}}</template>
</el-table-column>
</el-table>
<!--回访 结束-->
<!--有效沟通 开始-->
<el-table v-if="dialogObj.type == 'validchat'" :data="list" border size="small">
<el-table-column label="销售顾问" prop="staff_name"></el-table-column>
<el-table-column label="老师名" prop="teacher_name"></el-table-column>
<el-table-column label="UID" prop="user_id"></el-table-column>
<el-table-column label="客户微信昵称" prop="nick"></el-table-column>
<el-table-column label="电话号码">
<template slot-scope="scope">{{scope.row.mobile || '-'}}</template>
</el-table-column>
<el-table-column label="意向度">
<template slot-scope="scope">{{scope.row.intention || '-'}}</template>
</el-table-column>
<el-table-column label="最近备注时间">
<template slot-scope="scope">
<template v-if="scope.row.remark_time && String(scope.row.remark_time).indexOf(' ') > -1">
<div>{{String(scope.row.remark_time).split(' ')[0]}}</div>
<div>{{String(scope.row.remark_time).split(' ')[1]}}</div>
</template>
<template v-else>-</template>
</template>
</el-table-column>
<el-table-column label="下次回访时间">
<template slot-scope="scope">{{scope.row.next_visit_at || '-'}}</template>
</el-table-column>
</el-table>
<!--有效沟通 结束-->
<!--有效通次 开始-->
<el-table v-if="dialogObj.type == 'phonerecord'" :data="list" border size="small">
<el-table-column label="销售顾问" prop="staff_name"></el-table-column>
<el-table-column label="老师名" prop="teacher_name"></el-table-column>
<el-table-column label="UID" prop="user_id"></el-table-column>
<el-table-column label="客户名">
<template slot-scope="scope">{{scope.row.contact_name || '-'}}</template>
</el-table-column>
<el-table-column label="电话号码">
<template slot-scope="scope">{{scope.row.contact_phone || '-'}}</template>
</el-table-column>
<el-table-column label="意向度">
<template slot-scope="scope">{{scope.row.intention || '-'}}</template>
</el-table-column>
<el-table-column label="最近备注时间">
<template slot-scope="scope">
<template v-if="scope.row.remark_time && String(scope.row.remark_time).indexOf(' ') > -1">
<div>{{String(scope.row.remark_time).split(' ')[0]}}</div>
<div>{{String(scope.row.remark_time).split(' ')[1]}}</div>
</template>
<template v-else>-</template>
</template>
</el-table-column>
<el-table-column label="下次回访时间">
<template slot-scope="scope">{{scope.row.next_visit_at || '-'}}</template>
</el-table-column>
</el-table>
<!--有效通次 结束-->
<!--开课班级 开始-->
<el-table v-if="dialogObj.type == 'class'" :data="list" border size="small">
<el-table-column label="销售顾问" prop="staff_name"></el-table-column>
<el-table-column label="老师名" prop="teacher_name"></el-table-column>
<el-table-column label="期数名称" prop="user_id">
<template slot-scope="scope">
{{periodName(scope.row)}}
</template>
</el-table-column>
<el-table-column label="班级名称">
<template slot-scope="scope">{{scope.row.class_name || '-'}}</template>
</el-table-column>
<el-table-column label="开课时间">
<template slot-scope="scope">{{scope.row.start_at || '-'}}</template>
</el-table-column>
<el-table-column label="进班人数">
<template slot-scope="scope">{{scope.row.join_num || '-'}}</template>
</el-table-column>
</el-table>
<!--开课班级 结束-->
<!--业绩 开始-->
<el-table v-if="dialogObj.type == 'achievement'" :data="list" border size="small">
<el-table-column label="组别" width="60px">
<template slot-scope="scope">{{scope.row.squad ? `T${scope.row.squad}` : '-'}}</template>
</el-table-column>
<el-table-column label="销售顾问">
<!--todo 优化-->
<template slot-scope="scope">{{(dialogObj.isTotal || String(scope.row.staff_name).indexOf(',')>-1) ? '-' : dialogObj.staff_name}}</template>
</el-table-column>
<el-table-column label="平均转化率" prop="trans_rate"></el-table-column>
<el-table-column label="日课/体验课" prop="day_order_rate" width="90px"></el-table-column>
<el-table-column label="月课/季课" prop="month_order_rate"></el-table-column>
<el-table-column label="总订单" prop="total_order_num"></el-table-column>
<el-table-column label="一年课" prop="year_order_num">
<!--todo 跳转-->
</el-table-column>
<el-table-column label="两年课" prop="two_order_num">
<!--todo 跳转-->
</el-table-column>
<el-table-column label="总业绩" prop="total_order_money"></el-table-column>
<el-table-column label="一年课" prop="year_order_money"></el-table-column>
<el-table-column label="两年课" prop="two_order_money"></el-table-column>
</el-table>
<!--业绩 结束-->
<!--todo 权限有问题-->
<!--<page v-if="total" :total="total" :limit="limit" @pageChange="onPageChange" @sizeChange="onSizeChange"/>-->
<page :current-page="nowPage" :total="total" :limit="limit" @pageChange="onPageChange" @sizeChange="onSizeChange"/>
</div>
</el-dialog>
</template>
<script>
import {getVisitedApi, getClassOpenedApi, getAchievementApi, getPhoneRecordApi, getValidchatApi} from "@service/api";
import page from '@framework/page'
export default {
name: "TeamDialog",
components: {page},
props: {
dialogObj: {
type: Object,
required: true,
default: () => {}
}
},
data() {
return {
show: false,
loading: true,
list: [],
title: '',
total: 0,
nowPage: 1,
limit: 10,
}
},
mounted() {
this.initDialog()
},
methods: {
initDialog() {
// console.log(this.dialogObj)
if (this.dialogObj) {
this.show = this.dialogObj.show;
this.getData();
}
},
periodName(val) {
let str = '';
if (val.goods_id) {
str += `【${val.goods_id}】`
}
if (val.title) {
str += `${val.title}`
}
if (val.watch_num) {
str += `${val.watch_num}课时`
}
if (val.start_at) {
str += `(${val.start_at.slice(5).replace('-', '')})`
}
if (val.has_watch_num || val.has_watch_num == 0) {
str += `-d${val.has_watch_num}`
}
return str
},
getData() { // todo 名字
if (this.dialogObj.type == 'callback') {
this.getVisited();
this.title = `销售顾问:${this.dialogObj.staff_name} T${this.dialogObj.squad}`
} else if (this.dialogObj.type == 'validchat') {
this.getValidchat();
this.title = `销售顾问:${this.dialogObj.staff_name} T${this.dialogObj.squad}`
} else if (this.dialogObj.type == 'phonerecord') {
this.getPhonerecord();
this.title = `销售顾问:${this.dialogObj.staff_name} T${this.dialogObj.squad}`
} else if (this.dialogObj.type == 'class') {
this.getClass();
this.title = `销售顾问:${this.dialogObj.staff_name} T${this.dialogObj.squad}`
} else if (this.dialogObj.type == 'achievement') {
this.getAchievement();
this.title = `业绩详情:${this.dialogObj.staff_name} T${this.dialogObj.squad}`
}
},
getVisited() { // 已回访
let json = {
teacher_id: this.dialogObj.teacher_id,
// teacher_id: '82',
start_at: this.dialogObj.start_at,
page: this.nowPage,
limit: this.limit
}
getVisitedApi(json).then(res => {
this.list = res;
this.total = res.total || 0; // todo 后台没给分页
this.loading = false;
})
},
getValidchat() { // 有效沟通
let json = {
alias: this.dialogObj.alias,
teacher_id: this.dialogObj.teacher_id,
start_at: this.dialogObj.start_at,
page: this.nowPage,
limit: this.limit
}
getValidchatApi(json.alias, json).then(res => {
if (Object.keys(res).length && res.chat_friend_list) {
this.list = res.chat_friend_list.page_data;
this.total = res.chat_friend_list.total;
} else {
this.list = [];
this.total = 0;
}
this.loading = false;
})
},
getPhonerecord() {
let json = {
alias: this.dialogObj.alias,
teacher_id: this.dialogObj.teacher_id,
start_at: this.dialogObj.start_at,
page: this.nowPage,
limit: this.limit
}
getPhoneRecordApi(json.alias, json).then(res => {
if (Object.keys(res).length && res.phone_record_list) {
this.list = res.phone_record_list.page_data || [];
this.total = res.phone_record_list.total || 0;
} else {
this.list = [];
this.total = 0;
}
this.loading = false;
})
},
getClass() {
let json = {
teacher_id: this.dialogObj.teacher_id,
// teacher_id: 75,
start_at: this.dialogObj.start_at,
page: this.nowPage,
limit: this.limit
}
getClassOpenedApi(json).then(res => {
this.list = res;
this.total = res.total || 0;
this.loading = false;
})
},
getAchievement() {
let json = {
teacher_id: this.dialogObj.teacher_id,
user_id: this.dialogObj.user_id,
start_at: this.dialogObj.start_at,
page: this.nowPage,
limit: this.limit
}
getAchievementApi(json).then(res => {
if (typeof res === 'object') {
res.squad = this.dialogObj.squad;
res.staff_name = this.dialogObj.isTotal ? '-' : this.dialogObj.staff_name;
this.list = [res];
this.total = 0
}
this.loading = false;
})
},
onPageChange(val) {
this.nowPage = val
this.getData()
},
onSizeChange(val) {
this.limit = val;
this.nowPage = 1;
this.getData()
},
},
watch: {
dialogObj: {
handler: function () {
this.loading = true;
this.initDialog()
},
deep: true
},
show(value) {
this.nowPage = 1; // 重置
this.$emit("changeShow", value);
}
}
}
</script>
<template>
<div class="admin-refresh">
<el-date-picker
style="margin: 10px 0 0 10px; width: 185px;" :clearable="false"
v-model="search.start_at" value-format="yyyy-MM-dd"
align="right" type="date" placeholder="选择日期"
:picker-options="pickerOptions">
</el-date-picker>
<el-tabs v-model="search.team" type="card" class="tabs-refresh" @tab-click="getData">
<el-tab-pane label="总计" name="1,2,3,4,5,6,7,8,9,10"/>
<el-tab-pane v-for="i in 10" :key="i" :label="'T'+i" :name="i.toString()"/>
</el-tabs>
<el-table class="team-table" border size="small" :data="list" v-loading="loading" :row-class-name="tableRowClassName">
<el-table-column label="组别" width="50px">
<template slot-scope="scope">{{(String(scope.row.squad).indexOf(',') > -1 && scope.row.total) ? '合计' : `T${scope.row.squad}`}}</template>
</el-table-column>
<!--<el-table-column label="销售顾问">
<template slot-scope="scope">
<span v-html="transStaff(scope.row)"></span>
</template>
</el-table-column>-->
<el-table-column v-if="this.search.team != '1,2,3,4,5,6,7,8,9,10'" label="销售顾问">
<template slot-scope="scope">{{scope.row.total ? '-' : scope.row.staff_name}}</template>
</el-table-column>
<el-table-column prop="reach_class_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['reach_class_num']" placement="top">
<span class="table-refresh-header">
30 <i class="el-icon-question"></i><br>到班
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="reach_course_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['reach_course_num']" placement="top">
<span class="table-refresh-header">
30 <i class="el-icon-question"></i><br>到课
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="wait_add_friend">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['wait_add_friend']" placement="top">
<span class="table-refresh-header">
7 <i class="el-icon-question"></i><br>待添
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="wait_visit_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['wait_visit_num']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>待回访
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="over_visit_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['over_visit_num']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>已回访
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'callback')">{{scope.row.over_visit_num}}</span>
</template>
</el-table-column>
<el-table-column prop="chat_contact_count">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['chat_contact_count']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>微信沟
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="valid_chat_contact_count">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['valid_chat_contact_count']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>微信有效沟
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'validchat')">{{scope.row.valid_chat_contact_count}}</span>
</template>
</el-table-column>
<el-table-column prop="valid_phone_counts">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['valid_phone_counts']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>有效通
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'phonerecord')">{{scope.row.valid_phone_counts}}</span>
</template>
</el-table-column>
<el-table-column prop="phone_total_time">
<template slot="header" slot-scope="scope">
<!--TODO-->
<el-tooltip effect="dark" :content="TIP_TEAM['phone_total_time']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>有效通
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="lately_class_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['lately_class_num']" placement="top">
<span class="table-refresh-header">
未来7 <i class="el-icon-question"></i><br>开课班
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'class')">{{scope.row.lately_class_num}}</span>
</template>
</el-table-column>
<el-table-column prop="month_order_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['month_order_num']" placement="top">
<span class="table-refresh-header">
当月 <i class="el-icon-question"></i><br>订
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'achievement')">{{scope.row.month_order_num}}</span>
</template>
</el-table-column>
<el-table-column prop="month_order_rate">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['month_order_rate']" placement="top">
<span class="table-refresh-header">
当月 <i class="el-icon-question"></i><br>平均转
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'achievement')">
{{transRate(scope.row.month_trans_order_num, scope.row.month_trans_user_num)}}
</span>
</template>
</el-table-column>
<el-table-column prop="order_money_count">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['order_money_count']" placement="top">
<span class="table-refresh-header">
当月 <i class="el-icon-question"></i><br>总业
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'achievement')">{{scope.row.order_money_count}}</span>
</template>
</el-table-column>
</el-table>
<page :total="total" :limit="limit" @pageChange="onPageChange" @sizeChange="onSizeChange"/>
<team-dialog :dialog-obj="dialogObj"/>
</div>
</template>
<script>
import page from '@framework/page'
import TeamDialog from './dialog'
import {getTeamApi} from '@service/api';
import {TIP_TEAM} from '@util/tipArr';
function getNowFormatDate() {
var date = new Date();
var seperator1 = "-";
var year = date.getFullYear();//年
var month = date.getMonth() + 1;//月
var strDate = date.getDate(); //日
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = year + seperator1 + month + seperator1 + strDate;
return currentdate;
}
export default {
name: "index",
components: {page, TeamDialog},
data() {
return {
TIP_TEAM: TIP_TEAM,
loading: true,
search: {
team: '1',
start_at: getNowFormatDate()
// start_at: new Date()
},
pickerOptions: {
disabledDate(time) {
return time.getTime() > Date.now();
},
shortcuts: [{
text: '今天',
onClick(picker) {
picker.$emit('pick', new Date());
}
}, {
text: '昨天',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
picker.$emit('pick', date);
}
}, {
text: '一周前',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', date);
}
}]
},
list: [],
total: 0,
nowPage: 1,
limit: 10,
dialogObj: {
show: false,
type: '', // callback, class
}
}
},
mounted() {
this.getData();
},
methods: {
transStaff(row) {
if (row.total) {
return '合计'
} else if (row.staff_name.indexOf(',') > -1) {
return row.staff_name.split(',').join('<br>')
} else {
return row.staff_name
}
},
transRate(child, mother) {
if (mother) {
return `${Math.floor(child * 100) / mother}%`
} else {
return '-'
}
},
tableRowClassName({row, rowIndex}) {
if (rowIndex === 0) {
return 'primary-row';
}
return '';
},
dialogToggle(row, type) {
this.dialogObj = {
alias: row.alias, // 老师微信号
squad: (String(row.squad).indexOf(',') > -1 && row.total) ? '' : `${row.squad}`,
show: true,
total: row.total,
type: type,
user_id: row.user_id,
teacher_id: row.teacher_id,
start_at: this.search.start_at,
staff_name: row.staff_name.indexOf(',') > -1 ? row.staff_name.split(',').join(',') : row.staff_name
}
},
getData() {
this.loading = true;
let json = {
team: this.search.team,
page: this.nowPage,
limit: this.limit
}
getTeamApi(json).then(res => {
if (Object.keys(res).length && res.team_list && res.team_list.page_data) {
if (Object.keys(res.team_total).length) {
res.team_total.total = true; // 方便"合计" 可以这样写,也可以用scope.$index
res.team_list.page_data.unshift(res.team_total);
}
this.list = res.team_list.page_data;
this.total = res.team_list.total;
this.loading = false;
} else {
this.list = [];
this.total = 0;
this.loading = false;
}
})
},
onPageChange(val) {
this.nowPage = val
this.getData()
},
onSizeChange(val) {
this.limit = val;
this.nowPage = 1;
this.getData()
},
},
}
</script>
<style lang="less">
.team-table {
.primary-row {
background: #f5f7fa;
}
}
</style>
<template>
<div class="admin-refresh">
<el-date-picker
style="margin: 10px 0 0 10px; width: 185px;" :clearable="false"
v-model="search.start_at" value-format="yyyy-MM-dd"
align="right" type="date" placeholder="选择日期"
:picker-options="pickerOptions">
</el-date-picker>
<el-tabs v-model="search.team" type="card" class="tabs-refresh" @tab-click="getData">
<el-tab-pane label="总计" name="1,2,3,4,5,6,7,8,9,10"/>
<el-tab-pane v-for="i in 10" :key="i" :label="'T'+i" :name="i.toString()"/>
</el-tabs>
<el-table class="team-table" border size="small" :data="list" v-loading="loading" :row-class-name="tableRowClassName">
<el-table-column label="组别" width="50px">
<template slot-scope="scope">{{scope.row.isTotal ? '合计' : `T${scope.row.squad}`}}</template>
</el-table-column>
<!--<el-table-column label="销售顾问">
<template slot-scope="scope">
<span v-html="transStaff(scope.row)"></span>
</template>
</el-table-column>-->
<el-table-column v-if="this.search.team != '1,2,3,4,5,6,7,8,9,10'" label="销售顾问">
<template slot-scope="scope">{{scope.row.isTotal ? '-' : scope.row.staff_name}}</template>
</el-table-column>
<el-table-column prop="reach_class_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['reach_class_num']" placement="top">
<span class="table-refresh-header">
30 <i class="el-icon-question"></i><br>到班
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="reach_course_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['reach_course_num']" placement="top">
<span class="table-refresh-header">
30 <i class="el-icon-question"></i><br>到课
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="wait_add_friend">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['wait_add_friend']" placement="top">
<span class="table-refresh-header">
7 <i class="el-icon-question"></i><br>待添
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="wait_visit_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['wait_visit_num']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>待回访
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="over_visit_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['over_visit_num']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>已回访
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'callback')">{{scope.row.over_visit_num}}</span>
</template>
</el-table-column>
<el-table-column prop="chat_contact_count">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['chat_contact_count']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>微信沟
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="valid_chat_contact_count">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['valid_chat_contact_count']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>微信有效沟
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'validchat')">{{scope.row.valid_chat_contact_count}}</span>
</template>
</el-table-column>
<el-table-column prop="valid_phone_counts">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['valid_phone_counts']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>有效通
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'phonerecord')">{{scope.row.valid_phone_counts}}</span>
</template>
</el-table-column>
<el-table-column prop="phone_total_time">
<template slot="header" slot-scope="scope">
<!--TODO 时间展示-->
<el-tooltip effect="dark" :content="TIP_TEAM['phone_total_time']" placement="top">
<span class="table-refresh-header">
当日 <i class="el-icon-question"></i><br>有效通
</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="lately_class_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['lately_class_num']" placement="top">
<span class="table-refresh-header">
未来7 <i class="el-icon-question"></i><br>开课班
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'class')">{{scope.row.lately_class_num}}</span>
</template>
</el-table-column>
<el-table-column prop="month_order_num">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['month_order_num']" placement="top">
<span class="table-refresh-header">
当月 <i class="el-icon-question"></i><br>订
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'achievement')">{{scope.row.month_order_num}}</span>
</template>
</el-table-column>
<el-table-column prop="month_order_rate">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['month_order_rate']" placement="top">
<span class="table-refresh-header">
当月 <i class="el-icon-question"></i><br>平均转
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'achievement')">
{{transRate(scope.row.month_trans_order_num, scope.row.month_trans_user_num)}}
</span>
</template>
</el-table-column>
<el-table-column prop="order_money_count">
<template slot="header" slot-scope="scope">
<el-tooltip effect="dark" :content="TIP_TEAM['order_money_count']" placement="top">
<span class="table-refresh-header">
当月 <i class="el-icon-question"></i><br>总业
</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span class="cell-link" @click="dialogToggle(scope.row, 'achievement')">{{scope.row.order_money_count}}</span>
</template>
</el-table-column>
</el-table>
<page :total="total" :limit="limit" @pageChange="onPageChange" @sizeChange="onSizeChange"/>
<team-dialog :dialog-obj="dialogObj"/>
</div>
</template>
<script>
import page from '@framework/page'
import TeamDialog from './dialog'
import {getTeamApi} from '@service/api';
import {TIP_TEAM} from '@util/tipArr';
function getNowFormatDate() {
var date = new Date();
var seperator1 = "-";
var year = date.getFullYear(); // 年
var month = date.getMonth() + 1; // 月
var strDate = date.getDate(); // 日
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = year + seperator1 + month + seperator1 + strDate;
return currentdate;
}
export default {
name: "index",
components: {page, TeamDialog},
data() {
return {
isTotal: false,
TIP_TEAM: TIP_TEAM,
loading: true,
search: {
team: '1',
start_at: getNowFormatDate()
// start_at: new Date()
},
pickerOptions: {
disabledDate(time) {
return time.getTime() > Date.now();
},
shortcuts: [{
text: '今天',
onClick(picker) {
picker.$emit('pick', new Date());
}
}, {
text: '昨天',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
picker.$emit('pick', date);
}
}, {
text: '一周前',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', date);
}
}]
},
list: [],
total: 0,
nowPage: 1,
limit: 10,
dialogObj: {
show: false,
type: '', // callback, class
}
}
},
mounted() {
this.getData();
},
methods: {
transStaff(row) {
if (row.isTotal) {
return '合计'
} else if (row.staff_name.indexOf(',') > -1) {
return row.staff_name.split(',').join('<br>')
} else {
return row.staff_name
}
},
transRate(child, mother) {
if (mother) {
return `${Math.floor(child * 100) / mother}%`
} else {
return '-'
}
},
tableRowClassName({row, rowIndex}) {
if (rowIndex === 0) {
return 'primary-row';
}
return '';
},
dialogToggle(row, type) {
this.dialogObj = {
alias: row.alias, // 老师微信号
squad: (String(row.squad).indexOf(',') > -1 && row.isTotal) ? '' : `${row.squad}`,
show: true,
isTotal: row.isTotal,
type: type,
user_id: row.user_id,
teacher_id: row.teacher_id,
start_at: this.search.start_at,
staff_name: row.staff_name.indexOf(',') > -1 ? row.staff_name.split(',').join(',') : row.staff_name
}
},
getData() {
this.loading = true;
let json = {
team: this.search.team,
page: this.nowPage,
limit: this.limit
}
getTeamApi(json).then(res => {
if (Object.keys(res).length && res.team_list && res.team_list.page_data) {
if (Object.keys(res.team_total).length) {
res.team_total.isTotal = true; // 方便"合计" 可以这样写,也可以用scope.$index
res.team_list.page_data.unshift(res.team_total);
}
this.list = res.team_list.page_data;
this.total = res.team_list.total;
this.loading = false;
} else {
this.list = [];
this.total = 0;
this.loading = false;
}
})
},
onPageChange(val) {
this.nowPage = val
this.getData()
},
onSizeChange(val) {
this.limit = val;
this.nowPage = 1;
this.getData()
},
},
}
</script>
<style lang="less">
.team-table {
.primary-row {
background: #f5f7fa;
}
}
</style>
...@@ -267,36 +267,37 @@ ...@@ -267,36 +267,37 @@
this.callbackEdit.wechat.value = this.user.info.wx_number; this.callbackEdit.wechat.value = this.user.info.wx_number;
this.callbackEdit.wechat.origin = this.user.info.wx_number; this.callbackEdit.wechat.origin = this.user.info.wx_number;
}, },
'callbackObj.timestamp'() { 'callbackObj.timestamp'() { // 时间戳变化更新数据
this.user.user_id = this.callbackObj.user_id; this.initCallback();
this.getUser();
this.getTag();
} }
}, },
mounted() { mounted() {
this.user.user_id = this.callbackObj.user_id; this.initCallback();
if (!this.hasUserInfo) { },
this.getUser(); methods: {
} else { initCallback() {
this.user.info = this.callbackObj.info; this.user.user_id = this.callbackObj.user_id;
} if (!this.hasUserInfo) {
this.getTag(); this.getUser();
this.getData(); } else {
this.user.info = this.callbackObj.info;
if (this.callbackObj.teacher_id) {
let json = {
user_id: this.callbackObj.user_id
} }
getCallBackPrevApi(json).then(res => { this.getTag();
if (res && res[0] && res[0].next_visit_at && res[0].intention) { this.getData();
this.add.intention = res[0].intention;
this.add.next_visit_at = res[0].next_visit_at; if (this.callbackObj.teacher_id) {
let json = {
user_id: this.callbackObj.user_id
} }
}) getCallBackPrevApi(json).then(res => {
} if (res && res[0] && res[0].next_visit_at && res[0].intention) {
this.add.intention = res[0].intention;
this.add.next_visit_at = res[0].next_visit_at;
}
})
}
},
},
methods: {
filterName(string, type) { filterName(string, type) {
return this[type].find(i => { return this[type].find(i => {
return i.value == string return i.value == string
......
...@@ -525,7 +525,7 @@ ...@@ -525,7 +525,7 @@
import {INVITETYPE, ORDERSTATUS, BUYTYPE, USERSTATUSFORMATER} from "../../util/wordbook"; import {INVITETYPE, ORDERSTATUS, BUYTYPE, USERSTATUSFORMATER} from "../../util/wordbook";
import teacherDialog from './dialog' import teacherDialog from './dialog'
import UserList from '../class/userList' import UserList from '../class/userList'
import CallBack from '@/components/callBack/index' import CallBack from '@/components/userDetail/callBack';
import sourceByDateDialog from '../teacherDetail/sourceByDateDialog' import sourceByDateDialog from '../teacherDetail/sourceByDateDialog'
import AddressArray from "../framework/address-picker/addr"; import AddressArray from "../framework/address-picker/addr";
......
...@@ -6,7 +6,7 @@ import router from './router' ...@@ -6,7 +6,7 @@ import router from './router'
import store from './store' import store from './store'
import element_ui from 'element-ui' import element_ui from 'element-ui'
Vue.use(element_ui); Vue.use(element_ui);
Vue.config.productionTip = false Vue.config.productionTip = false;
/* eslint-disable no-new */ /* eslint-disable no-new */
new Vue({ new Vue({
......
...@@ -1469,3 +1469,19 @@ export const putBrokerageApi = function (id, json) { ...@@ -1469,3 +1469,19 @@ export const putBrokerageApi = function (id, json) {
export const deleteBrokerageApi = function (id) { export const deleteBrokerageApi = function (id) {
return Vue.prototype.$del(`${_baseUrl}api/admin/bkge/config/${id}`) return Vue.prototype.$del(`${_baseUrl}api/admin/bkge/config/${id}`)
}; };
// 获取团队概况
export const getTeamApi = function (json) {
return Vue.prototype.$fetch(`${_baseUrl}api/admin/teacher/teamprofile`, json)
};
// 获取已回访列表
export const getVisitedApi = function (json) {
return Vue.prototype.$fetch(`${_baseUrl}api/admin/teacher/overvisitlist`, json)
};
// 获取最近开班列表
export const getClassOpenedApi = function (json) {
return Vue.prototype.$fetch(`${_baseUrl}api/admin/teacher/reachstartclasslist`, json)
};
// 获取业绩详情
export const getAchievementApi = function (json) {
return Vue.prototype.$fetch(`${_baseUrl}api/admin/teacher/teamachievement`, json)
};
...@@ -32,8 +32,7 @@ axios.interceptors.request.use( ...@@ -32,8 +32,7 @@ axios.interceptors.request.use(
config.params = config.params || {}; config.params = config.params || {};
let json = JSON.parse(JSON.stringify(config.params)); let json = JSON.parse(JSON.stringify(config.params));
// console.log(json) // console.log(json)
for(let k in json) for(let k in json) {
{
// let reg = /^[0-9]+$/u; // let reg = /^[0-9]+$/u;
// if(reg.test(json[k])){ // if(reg.test(json[k])){
// console.log(json[k]) // console.log(json[k])
......
...@@ -115,6 +115,26 @@ export default [ ...@@ -115,6 +115,26 @@ export default [
name: 'teacher', name: 'teacher',
component: e => require(['@/components/teacher'], e), component: e => require(['@/components/teacher'], e),
} }
}, {
value: '增长运营列表', // 增长运营、TMK用
routerName: 'growth',
path: '/growth',
cover: '3-6',
router: {
path: '/growth',
name: 'growth',
component: e => require(['@/components/teacher/growth'], e),
}
}, {
value: '用户服务列表', // 用户服务用
routerName: 'userservice',
path: '/userservice',
cover: '3-7',
router: {
path: '/userservice',
name: 'userservice',
component: e => require(['@/components/teacher/userservice'], e),
}
}, { }, {
value: '月课订单列表', value: '月课订单列表',
routerName: 'monthOrder', routerName: 'monthOrder',
...@@ -185,7 +205,28 @@ export default [ ...@@ -185,7 +205,28 @@ export default [
name: 'brokerage', name: 'brokerage',
component: e => require(['@/components/brokerage'], e), component: e => require(['@/components/brokerage'], e),
} }
}, {
value: '团队概况',
routerName: 'team',
path: '/team',
cover: '11-9',
router: {
path: '/team',
name: 'team',
component: e => require(['@/components/team'], e),
}
}, },
/*{
value: '小时动态',
routerName: 'hour',
path: '/hour',
cover: '11-10',
router: {
path: '/hour',
name: 'hour',
component: e => require(['@/components/team/hour'], e),
}
},*/
] ]
}, { }, {
name: '', name: '',
......
export const tipArr = { export const tipArr = {
'到课率':'浏览过一次及以上课包的人数/学员人数;不含观摩班', '到课率': '浏览过一次及以上课包的人数/学员人数;不含观摩班',
'看课率':'(课包浏览数量*看课学员数)/(已解锁课包数*学员人数);不含观摩班', '看课率': '(课包浏览数量*看课学员数)/(已解锁课包数*学员人数);不含观摩班',
'完课率':'浏览过所有课包的人数/学员人数;不含观摩班', '完课率': '浏览过所有课包的人数/学员人数;不含观摩班',
'打卡率':'完成过一次及以上课包分享的人数/学员数;不含观摩班', '打卡率': '完成过一次及以上课包分享的人数/学员数;不含观摩班',
'全勤打卡率':'完成过所有课包分享的人数/学员数;不含观摩班', '全勤打卡率': '完成过所有课包分享的人数/学员数;不含观摩班',
'转化率':'晚于体验营开课时间的正式课购课学员数量/学员数;不含观摩班', '转化率': '晚于体验营开课时间的正式课购课学员数量/学员数;不含观摩班',
}; };
export const tipArr2 = { export const tipArr2 = {
'订单数':'支付成功且未全额退款的订单数量(*月课、季课全勤返现完成的订单也会排除)', '订单数': '支付成功且未全额退款的订单数量(*月课、季课全勤返现完成的订单也会排除)',
'到班数':'进入系统课程期数班级的学员数量', '到班数': '进入系统课程期数班级的学员数量',
'到班率':'到班数/订单数', '到班率': '到班数/订单数',
'好友数':'班主任在系统内标注用已成为微信好友的户数量,包含老师主动添加数和用户主动添加数', '好友数': '班主任在系统内标注用已成为微信好友的户数量,包含老师主动添加数和用户主动添加数',
'到课数':'浏览过一次及以上课包的人数', // '到课数':'浏览过一次及以上课包的人数',
'好友率':'好友数/订单数', '好友率': '好友数/订单数',
'到课数':'浏览过一次及以上课包的人数', '到课数': '浏览过一次及以上课包的人数',
'到课率':'到课数/订单数', '到课率': '到课数/订单数',
'转化人数':'购买一年课、两年课且未全额退款的人数(*个别退课但未全额退款的学员包含在内)', '转化人数': '购买一年课、两年课且未全额退款的人数(*个别退课但未全额退款的学员包含在内)',
'转化率':'转化人数/订单数', '转化率': '转化人数/订单数',
'一年课购买人数':'购买一年课且未全额退款的人数', '一年课购买人数': '购买一年课且未全额退款的人数',
'两年课购买人数':'购买两年课且未全额退款的人数', '两年课购买人数': '购买两年课且未全额退款的人数',
'转化总额':'一年课和两年课的转化金额合计', '转化总额': '一年课和两年课的转化金额合计',
'一年课转化金额':'购买一年课且未全额退款的订单实付金额(云集订单为商品金额,不扣除优惠券、抵现)', '一年课转化金额': '购买一年课且未全额退款的订单实付金额(云集订单为商品金额,不扣除优惠券、抵现)',
'两年课转化金额':'购买两年课且未全额退款的订单实付金额(云集订单为商品金额,不扣除优惠券、抵现)', '两年课转化金额': '购买两年课且未全额退款的订单实付金额(云集订单为商品金额,不扣除优惠券、抵现)',
}; };
export const tipArr3 = { export const tipArr3 = {
'到班数':'进入系统课程期数班级的学员数量', '到班数': '进入系统课程期数班级的学员数量',
'好友数':'班主任在系统内标注用已成为微信好友的户数量,包含老师主动添加数和用户主动添加数', '好友数': '班主任在系统内标注用已成为微信好友的户数量,包含老师主动添加数和用户主动添加数',
'到课数':'浏览过一次及以上课包的人数', // '到课数':'浏览过一次及以上课包的人数',
'好友率':'好友数/到班数', '好友率': '好友数/到班数',
'到课数':'浏览过一次及以上课包的人数', '到课数': '浏览过一次及以上课包的人数',
'到课率':'到课数/到班数', '到课率': '到课数/到班数',
'转化人数':'购买一年课、两年课且未全额退款的人数(*个别退课但未全额退款的学员包含在内)', '转化人数': '购买一年课、两年课且未全额退款的人数(*个别退课但未全额退款的学员包含在内)',
'转化率':'转化人数/到班数', '转化率': '转化人数/到班数',
'一年课购买人数':'购买一年课且未全额退款的人数', '一年课购买人数': '购买一年课且未全额退款的人数',
'两年课购买人数':'购买两年课且未全额退款的人数', '两年课购买人数': '购买两年课且未全额退款的人数',
'转化总额':'一年课和两年课的转化金额合计', '转化总额': '一年课和两年课的转化金额合计',
'一年课转化金额':'购买一年课且未全额退款的订单实付金额(云集订单为商品金额,不扣除优惠券、抵现)', '一年课转化金额': '购买一年课且未全额退款的订单实付金额(云集订单为商品金额,不扣除优惠券、抵现)',
'两年课转化金额':'购买两年课且未全额退款的订单实付金额(云集订单为商品金额,不扣除优惠券、抵现)', '两年课转化金额': '购买两年课且未全额退款的订单实付金额(云集订单为商品金额,不扣除优惠券、抵现)',
}; };
\ No newline at end of file export const TIP_TEAM = {
'reach_class_num': '近30天,进入系统课程期数班级的学员数', // 到班数
'reach_course_num': '近30天,浏览过1次以上课件的学员数', // 到课数
'wait_add_friend': '近7天,到班,但没有添加好友', // 待添加
'wait_visit_num': '当天待回访的学员数(标记了回访日期,回访日期=查询日,且没有回访行为)', // 待回访
'over_visit_num': '当天做了回访的学员数', // 已回访
'chat_contact_count': '当天CC在微信中发出去的信息条数(不包括群)', // 微信沟通
'valid_chat_contact_count': '当天CC在微信1对1沟通中有1轮以上回复的条数(CC发出一条,客户回复一条)', // 微信有效沟通
'valid_phone_counts': '当天接通的电话次数', // 有效通次
'phone_total_time': '当天接通的电话通时,格式为hms,小时分钟秒', // 有效通时
'lately_class_num': '当天往后推7自然日内,关联到该CC的开期的班的数量', // 未来开课
'month_order_num': '年、两年课的订单总和(除去全额退款的)', // 当月订单
'month_order_rate': '当月订单数/当月到班人数', // 当月转化
'order_money_count': '当月一年、两年课的业绩(减掉全额退款的)', // 当月业绩
};
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