<template> <div style="font-size: 14px"> <el-row :gutter="20"> <el-col :span="24"> <task1 :teacherId="id"></task1> </el-col> </el-row> <el-row :gutter="20" style="margin-top: 20px"> <el-col :span="24"> <task3 :task3List="task3List" :teacherId="id" :refDesc3="refDesc3"></task3> </el-col> </el-row> <el-row :gutter="20" style="margin-top: 20px"> <el-col :span="24"> <el-card> <div slot="header" class="clearfix"> <span style="font-size: 18px;font-weight: bold">任务3:意向用户标记</span> </div> <div>本期意向用户:</div> <div v-if="!task3List || task3List.length < 1" style="color: #DDDDDD;text-align: center"> ——暂无数据—— </div> <div v-for="data in task3List" class="task3-table" style="width:47%"> <div class="table" > <div class="title" style="width:8%"> <div class="header bg-h">期数</div> <div> {{data.title}} </div> </div> <div class="over_work" style="background-color: #fffbe4"> <div class="header bg-h">今日需沟通用户</div> <el-button size="mini" type="text" style="font-size: 30px;text-decoration:underline" @click="showOverWorkDetail(data)">{{data.total_watch_user_num}}</el-button> </div> <div class="recall_process" style="line-height: 30px"> <div class="header bg-h">完成情况</div> <div style="text-align:left;margin-left:20px;">用户已标记:{{ data.total_over_intention_num }}人</div> <div style="text-align:left;margin-left:20px;">老师已沟通:{{ data.total_over_num }}人</div> <div style="text-align:left;margin-left:20px;">用户标记率: <el-progress style="display: inline-block;width: 120px" :text-inside="true" :stroke-width="18" :color="Number(data.over_intention_rate)===100 ? '#67C23A' : '#f00'" :percentage="Number(data.over_intention_rate)"> </el-progress> </div> <div style="text-align:left;margin-left:20px;">任务处理率: <el-progress style="display: inline-block;width: 120px" :text-inside="true" :stroke-width="18" :color="Number(data.over_rate)===100? '#67C23A' : '#f00'" :percentage="Number(data.over_rate)"></el-progress> </div> </div> <!-- <div class="recall" style="background-color: #fffbe4"> <div class="header bg-h">今日需召回人数</div> <el-button size="mini" style="font-size: 30px;text-decoration:underline " type="text" @click="showRecallDetail(data)">{{data.need_recall_user_num}}</el-button> </div>--> </div> </div> <br> <div>往期意向用户:</div> <div class="task3-table" style="width:47%"> <div class="table" > <div class="title" style="width:8%"> <div class="header bg-h">期数</div> <div> 往期活跃用户数(近三天) </div> </div> <div class="over_work" style="background-color: #fffbe4"> <div class="header bg-h">今日需沟通用户</div> <el-button size="mini" type="text" style="font-size: 30px;text-decoration:underline" @click="showTask5Detail()">{{task5Detail.total}}</el-button> </div> <div class="recall_process"> <div class="header bg-h">完成情况</div> <div style="text-align:left;margin-left:20px;line-height: 30px">用户已标记:{{ task5Detail.total_over_intention_num }}人</div> <div style="text-align:left;margin-left:20px;line-height: 30px">老师已沟通:{{ task5Detail.total_over_num}}人</div> <div style="text-align:left;margin-left:20px;line-height: 30px">用户标记率: <el-progress style="display: inline-block;width: 120px" :text-inside="true" :stroke-width="18" :color="Number(task5Detail.over_intention_rate)===100 ? '#67C23A' : '#f00'" :percentage="Number(task5Detail.over_intention_rate)"> </el-progress> </div> <div style="text-align:left;margin-left:20px;line-height: 30px">任务处理率: <el-progress style="display: inline-block;width: 120px" :text-inside="true" :stroke-width="18" :color="Number(task5Detail.over_rate)===100? '#67C23A' : '#f00'" :percentage="Number(task5Detail.over_rate)"></el-progress> </div> </div> </div> </div> </el-card> </el-col> </el-row> <el-row :gutter="20" style="margin-top: 20px"> <el-col :span="12"> <task2 :teacherId="id"></task2> </el-col> </el-row> <el-dialog append-to-body :visible.sync="task3Detail.show" width="80%" :title="task3Detail.title" > <el-table :data="task3Detail.list" v-loading="task3Detail.loading" size="mini" style="width: 100%" fixed> <el-table-column label="用户" className="f-c" min-width="180" prop="user_id"> <template slot-scope="scope"> <img :src="scope.row.avatar" style="width: 40px;min-width:40px;height: 40px;border-radius: 50px"> {{scope.row.nickname}}(ID:{{scope.row.user_id}}) <br> Tel:{{scope.row.mobile}} </template> </el-table-column> <el-table-column min-width="260" label="沟通情况"> <template slot-scope="scope"> <teacher-desc :row="scope.row" :descType="2" @onSuccess="refDesc3"></teacher-desc> </template> </el-table-column> <el-table-column label="用户反馈"> <template slot-scope="scope"> <span v-if="scope.row.is_reply"> <span v-if="scope.row.reply_content">{{scope.row.reply_content}}</span> <span v-if="!scope.row.reply_content || scope.row.reply_content === ''">无内容</span> </span> <span v-if="!scope.row.is_reply" style="color: red">尚未回复</span> </template> </el-table-column> <el-table-column label="进班时间" min-width="200" sortable prop="created_at" > </el-table-column> <el-table-column label="用户属性" min-width="400" sortable prop="last_login_at" > <template slot-scope="scope"> 最后登录时间:{{scope.row.last_login_at}} <br> 是否添加老师:{{scope.row.is_add_teacher | ADDTEACHER}} <br> 用户意向等级:{{scope.row.weight}} </template> </el-table-column> <el-table-column label="操作" width="100px" fixed="right"> <template slot-scope="scope"> <el-button type="info" size="mini" @click="showLook(scope.row)">看课情况</el-button> </template> </el-table-column> </el-table> </el-dialog> <el-dialog append-to-body :visible.sync="lookDetail.show"> <el-table v-loading="lookDetail.loading" :data="lookDetail.list" style="width: 100%"> <el-table-column prop="start_at" label="日期"> </el-table-column> <el-table-column label="爸妈看一看"> <template slot-scope="scope"> <span v-if="scope.row.watch_list && scope.row.watch_list.length > 0 && scope.row.watch_list.find(i=>{return i.page_id === 1})"> {{scope.row.watch_list.find(i=>{return i.page_id === 1}).stay_time}} </span> <span v-if="!scope.row.watch_list.find(i=>{return i.page_id === 1})"> 暂未上课 </span> </template> </el-table-column> <el-table-column label="宝贝玩一玩"> <template slot-scope="scope"> <span v-if="scope.row.watch_list && scope.row.watch_list.length > 0 && scope.row.watch_list.find(i=>{return i.page_id === 2})"> {{scope.row.watch_list.find(i=>{return i.page_id === 2}).stay_time}} </span> <span v-if="!scope.row.watch_list.find(i=>{return i.page_id === 2})"> 暂未上课 </span> </template> </el-table-column> <el-table-column label="爸妈秀宝贝"> <template slot-scope="scope"> <span v-if="scope.row.watch_list && scope.row.watch_list.length > 0 && scope.row.watch_list.find(i=>{return i.page_id === 3})"> <div v-html="scope.row.watch_list.find(i=>{return i.page_id === 3}).learn_report"></div> </span> <span v-if="!scope.row.watch_list.find(i=>{return i.page_id === 3})"> 暂未秀宝贝 </span> </template> </el-table-column> <el-table-column label="多元趣味课"> <template slot-scope="scope"> <span v-if="scope.row.watch_list && scope.row.watch_list.length > 0 && scope.row.watch_list.find(i=>{return i.page_id === 5})"> {{scope.row.watch_list.find(i=>{return i.page_id === 5}).stay_time}} </span> <span v-if="!scope.row.watch_list.find(i=>{return i.page_id === 5})"> 暂未上课 </span> </template> </el-table-column> <el-table-column label="分享"> <template slot-scope="scope"> <span v-if="scope.row.watch_list && scope.row.watch_list.length > 0 && scope.row.watch_list.find(i=>{return i.page_id === 4})"> 已分享 </span> <span v-if="!scope.row.watch_list.find(i=>{return i.page_id === 4})"> 暂未分享 </span> </template> </el-table-column> </el-table> </el-dialog> <el-dialog append-to-body :visible.sync="task2Detail.show" :title="task2Detail.title" width="80%"> <el-table :data="task2Detail.list" size="mini" style="width: 100%" fixed> <el-table-column label="用户" className="f-c" min-width="180" prop="user_id"> <template slot-scope="scope"> <img :src="scope.row.avatar" style="width: 40px;min-width:40px;height: 40px;border-radius: 50px"> {{scope.row.nickname}}(ID:{{scope.row.user_id}}) <br> Tel:{{scope.row.mobile}} </template> </el-table-column> <el-table-column min-width="160" label="沟通情况"> <template slot-scope="scope"> <teacher-desc :row="scope.row" :descType="1" @onSuccess="refDesc2"></teacher-desc> </template> </el-table-column> <el-table-column label="用户反馈"> <template slot-scope="scope"> <span v-if="scope.row.is_reply"> <span v-if="scope.row.reply_content">{{scope.row.reply_content}}</span> <span v-if="!scope.row.reply_content || scope.row.reply_content === ''">无内容</span> </span> <span v-if="!scope.row.is_reply" style="color: red">尚未回复</span> </template> </el-table-column> <el-table-column label="学习情况" min-width="180" prop="weight"> <template slot-scope="scope"> 学习总时长:{{scope.row.total_stay_time}}秒 <br> 学习课包模块数:{{scope.row.total_times}}次 <br> 最后看课时间:{{scope.row.last_watch_at}} </template> </el-table-column> <el-table-column label="意向等级" min-width="95" prop="weight"> <template slot-scope="scope"> <user-weight :row="scope.row" @onSuccess="changeWeight"></user-weight> </template> </el-table-column> <el-table-column prop="last_watch_at" label="最后标注时间"> <template slot-scope="scope"> {{scope.row.last_weight_at?scope.row.last_weight_at:'-'}} </template> </el-table-column> <el-table-column prop="last_weight_desc" label="标注意向原因"> <template slot-scope="scope"> {{scope.row.last_weight_desc?scope.row.last_weight_desc:'-'}} </template> </el-table-column> </el-table> </el-dialog> <el-dialog append-to-body :visible.sync="task5Detail.show" width="80%" title="往期活跃用户列表"> <el-table :data="task5Detail.list" size="mini" style="width: 100%" fixed> <el-table-column label="期数信息" min-width="120" prop="weight"> <template slot-scope="scope"> {{scope.row.title}} </template> </el-table-column> <el-table-column label="用户" className="f-c" min-width="180" prop="user_id"> <template slot-scope="scope"> <img :src="scope.row.avatar" style="width: 40px;min-width:40px;height: 40px;border-radius: 50px"> {{scope.row.nickname}}(ID:{{scope.row.user_id}}) <br> Tel:{{scope.row.mobile}} </template> </el-table-column> <el-table-column label="沟通情况"> <template slot-scope="scope"> <teacher-desc :row="scope.row" :descType="1" @onSuccess="getTask5"></teacher-desc> </template> </el-table-column> <el-table-column label="用户反馈"> <template slot-scope="scope"> <span v-if="scope.row.is_reply"> <span v-if="scope.row.reply_content">{{scope.row.reply_content}}</span> <span v-if="!scope.row.reply_content || scope.row.reply_content === ''">无内容</span> </span> <span v-if="!scope.row.is_reply" style="color: red">尚未回复</span> </template> </el-table-column> <el-table-column label="学习情况" min-width="180" prop="weight"> <template slot-scope="scope"> 学习总时长:{{scope.row.total_stay_time}}秒 <br> 学习课包模块数:{{scope.row.total_times}}次 <br> 最后看课时间:{{scope.row.created_at}} </template> </el-table-column> <el-table-column label="意向等级" min-width="95" prop="weight"> <template slot-scope="scope"> <user-weight :row="scope.row" @onSuccess="getTask5"></user-weight> </template> </el-table-column> <el-table-column prop="last_watch_at" label="最后标注时间"> <template slot-scope="scope"> {{scope.row.last_watch_at?scope.row.last_watch_at:'-'}} </template> </el-table-column> <el-table-column prop="last_weight_desc" label="标注意向原因"> <template slot-scope="scope"> {{scope.row.last_weight_desc?scope.row.last_weight_desc:'-'}} </template> </el-table-column> </el-table> </el-dialog> </div> </template> <script> import {userLookApi,task5Api,getWatchUserApi,task3Api,getOverWatchListApi,getRecallListApi,addPeriodsClassUserDescApi,getUserDescListApi,changeAddTeacherApi,editUserWeightApi,editUserViewCourseApi} from "../../service/api"; import teacherDesc from '../framework/teacherDesc' import userWeight from '../framework/userWeight' import task1 from './task1' import task2 from './task2' import task3 from './task3' export default { name: "task", components: {teacherDesc,task1,task2,task3,userWeight}, props:[ 'parentDetail' ], data(){ return { id:this.parentDetail ? this.parentDetail.id : this.$route.params.id, task3List:[], task2Detail:{ show:false, list:[], type:1, weight:'' }, lookDetail:{ show:false, loading:false, list:[], nowPage: 1, data:null, limit: 500, total:0 }, task1Detail:{ show:false, list:[], title:'', cur_date:'' }, task5Detail:{ show:false, list:[], total:0, total_over_num:0, over_rate:0, total_over_reply_num:0, total_over_intention_num:0, over_intention_rate:0, over_reply_rate:0, }, recallDetail:{ show:false, list:[], weight:'' }, overWorkDetail:{ show:false, list:[], weight:'' }, descDialog:{ show:false, id:'', descList:[], user_info:null, type:null }, task3Detail:{ show:false, list:[], is_true:'', is_watch:'', loading:false, periods_id:'', cur_date:'', title:'', type:0, }, dialogType:0 } }, methods:{ showLook(data){ if(data){ this.lookDetail.data = data } this.lookDetail.show = true; this.lookDetail.loading = true; let json = { limit: this.lookDetail.limit, page: this.lookDetail.nowPage }; userLookApi(this.lookDetail.data.periods_id,this.lookDetail.data.user_id, json).then(res=>{ this.lookDetail.list = res.list; this.lookDetail.loading = false; this.lookDetail.total = res.total; }) }, onLookDetailPageChange(val){ this.lookDetail.nowPage = val this.showLook(); }, onLookDetailSizeChange(val){ this.lookDetail.limit = val this.lookDetail.nowPage = 1; this.showLook(); }, showTask3Detail(data,is_true,is_watch,cur_date){ let json={ is_true:is_true, is_watch:is_watch, cur_date:cur_date }; this.task3Detail.show = true; this.task3Detail.loading = true; this.task3Detail.is_true = is_true; this.task3Detail.periods_id = data.periods_id; this.task3Detail.is_watch = is_watch; this.task3Detail.cur_date = cur_date; this.task3Detail.type = 1; this.dialogType = 3; this.task3Detail.title=`【${data.periods_id}】${data.title} ${is_true === 1 ? '已' : '未'}${is_watch === 1 ? '看课' : '打卡'}学员` getWatchUserApi(data.periods_id,this.id,json).then(res=>{ this.task3Detail.loading = false; this.task3Detail.list = res }) }, showOverWorkDetail(data){ let json={}; this.task2Detail.show = true; this.task2Detail.loading = true; this.task2Detail.periods_id = data.periods_id; this.task2Detail.type = 2; this.task2Detail.title=`${data.title} 截止今日全勤学员`; this.dialogType = 2; getOverWatchListApi(data.periods_id,this.id,json).then(res=>{ this.task2Detail.loading = false; this.task2Detail.list = res }) }, showRecallDetail(data) { let json={}; this.task3Detail.show = true; this.task3Detail.loading = true; this.task3Detail.periods_id = data.periods_id; this.task3Detail.type = 3; this.task3Detail.title=`${data.title} 今日需要招回学员`; this.dialogType = 3; getRecallListApi(data.periods_id,this.id,json).then(res=>{ this.task3Detail.loading = false; this.task3Detail.list = res }) }, editComment(id,flag) { this.$prompt('', '添加沟通话术', { confirmButtonText: '确定', cancelButtonText: '取消', inputValue: '' }).then(({ value }) => { addPeriodsClassUserDescApi(id,{desc: value}).then(res=>{ this.$message({ type: 'success', message: '添加沟通话术成功' }); switch(this.dialogType) { case 2: this.refDesc2(); break; case 3: this.refDesc3(); break; case 4: this.getTask5(); break; } }); }) }, refDesc3(){ if(this.task3Detail.type === 1){ let json={ is_true:this.task3Detail.is_true, is_watch:this.task3Detail.is_watch, cur_date:this.task3Detail.cur_date }; this.task3Detail.loading = true; getWatchUserApi(this.task3Detail.periods_id,this.id,json).then(res=>{ this.task3Detail.loading = false; this.task3Detail.show = true; this.task3Detail.list = res }) }else if (this.task3Detail.type === 2){ getOverWatchListApi(this.task3Detail.periods_id,this.id,{}).then(res=>{ this.task3Detail.loading = false; this.task3Detail.show = true; this.task3Detail.list = res }) }else if(this.task3Detail.type === 3) { getRecallListApi(this.task3Detail.periods_id,this.id,{}).then(res=>{ this.task3Detail.loading = false; this.task3Detail.show = true; this.task3Detail.list = res }) } task3Api(this.id).then(res=>{ this.task3List = res }); }, showTask5Detail(){ this.task5Detail.show=true; this.dialogType = 4; }, refDesc2(){ if(this.task2Detail.type === 1){ task2Api(this.id).then(res=>{ this.task2List = res; res.forEach(i=>{ if(i.weight === this.task2Detail.weight){ this.task2Detail.list = i.detail } }) }); }else if(this.task2Detail.type === 2) { getOverWatchListApi(this.task2Detail.periods_id,this.id,{}).then(res=>{ this.task2Detail.loading = false; this.task2Detail.list = res }) task3Api(this.id).then(res=>{ this.task3List = res }); } }, changeAddTeacher(data){ changeAddTeacherApi(data.id,data.is_add_teacher).then(()=>{ this.$message({ type:'success', message:'数据更改成功' }); this.refDesc2() }) }, changeAddTeacher3(data){ changeAddTeacherApi(data.id,data.is_add_teacher).then(()=>{ this.$message({ type:'success', message:'数据更改成功' }); this.refDesc3(); }) }, changeWeight3(data){ editUserWeightApi(data.id,data.weight).then(()=>{ this.$message({ type:'success', message:'数据更改成功' }); this.refDesc3() }) }, changeWeight(data,type){ if(type === 5){ this.getTask5() }else{ this.refDesc2() } }, changeView(data){ editUserViewCourseApi(data.id,data.is_view_course).then(()=>{ this.$message({ type:'success', message:'数据更改成功' }); this.refDesc2() }) }, editDesc3(data){ this.$prompt('', '请输入沟通情况', { confirmButtonText: '确定', cancelButtonText: '取消', }).then(({ value }) => { addPeriodsClassUserDescApi(data.id,{desc:value}).then(res=>{ this.$message({ type:'success', message:'更新成功' }); this.refDesc3(); }) }).catch(() => { }); }, editDesc(data,type){ this.descDialog.show = true; this.descDialog.id = data.id; this.descDialog.type = type ? type : null; this.descDialog.user_info = { avatar:data.avatar, nickname:data.nickname, user_id:data.user_id, }; this.getUserDescList() }, getUserDescList(){ getUserDescListApi(this.descDialog.id,{limit:1000}).then(res=>{ this.descDialog.descList = res.list }) }, getTask5(){ task5Api(this.id).then(res=>{ this.task5Detail.list = res.list; this.task5Detail.total = res.total; this.task5Detail.over_rate = res.over_rate; this.task5Detail.total_over_num = res.total_over_num; this.task5Detail.over_reply_rate = res.over_reply_rate; this.task5Detail.total_over_reply_num = res.total_over_reply_num; this.task5Detail.total_over_intention_num = res.total_over_intention_num; this.task5Detail.over_intention_rate = res.over_intention_rate }); }, initPage(){ task3Api(this.id).then(res=>{ this.task3List = res }); this.getTask5() } }, filters:{ ADDTEACHER(value){ let str = ''; if(value === 0){ str = '暂未处理' }else if(value === 1){ str = '老师主动添加用户' }else if(value === 2){ str = '用户主动添加老师' }else if(value === 3){ str = '待通过' }else if(value === 4){ str = '手机号不是微信号' }else if(value === 5){ str = '用户已拒绝' } return str } }, mounted(){ this.initPage() } } </script> <style scoped lang="less"> @import "../../util/public"; .task3-table{ padding: 10px; overflow: auto; display: inline-block; .table{ &:after{ content:''; display: block; clear: both; } &>div{ display: table-cell; white-space:nowrap; vertical-align: middle; height: 192px; width: auto; text-align: center; position: relative; border: 1px solid #f0f0f0; &.title{ min-width: 200px; } &.start{ min-width: 100px; } &.total{ min-width: 90px; } &.watch{ min-width: 90px; } &.over_work{ min-width: 120px; } &.recall{ min-width: 110px; } .header{ position: absolute; width: 100%; left: 0; top: 0; height: 21px; border-bottom: 1px solid #f0f0f0; padding: 5px 0; text-align: center; } } .log-list>div{ text-align: center; padding: 5px 15px; border-bottom: 1px solid #f0f0f0; line-height: normal; } } } .bg-h{ background: rgb(228, 239, 247); } /deep/ .hightLight{ background: rgb(255, 251, 228); } </style>