Commit 7f5b7dfc authored by Mac's avatar Mac

新增2个统计页面

parent 186605a9
......@@ -227,3 +227,24 @@ export function querySupplierType() {
method: 'post',
})
}
/**
* 获取学员跟踪分页列表
*/
export function getStudentFollowUpPageList(data) {
return request({
url: '/StudentStat/GetStudentFollowUpPageList',
method: 'post',
data
})
}
/**
* 获取客人咨询分页列表
*/
export function getStudentConsultPageList(data) {
return request({
url: '/StudentStat/GetStudentConsultPageList',
method: 'post',
data
})
}
\ No newline at end of file
<style>
@import "../financial/css/cssReset.css";
.baseSet_Title {
width: 120px !important;
padding: 18px 0 0 16px;
text-align: right;
}
.singeRowTable tr th {
border: 1px solid #d2d2d2;
}
td:first-child{background-color: #E6E6E6;position: sticky;left:0px;}
th:first-child{position: sticky;left:0px;}
</style>
<template>
<div class="page-body marketRules">
<div class="page-search row items-center">
<div class="col row wrap q-mr-lg q-col-gutter-md">
<div class="col-3">
<q-input @input="resetSearch" dense clearable filled v-model="msg.StuName" label="昵称" maxlength="20" />
</div>
<div class="col-3">
<q-input @input="resetSearch" dense clearable filled v-model="msg.StuRealMobile" label="电话" maxlength="20" />
</div>
<div class="col-3">
<q-input @input="resetSearch" dense clearable filled v-model="msg.QQ" label="QQ" maxlength="20" />
</div>
<div class="col-3">
<q-input @input="resetSearch" dense clearable filled v-model="msg.WeChatNo" label="微信号" maxlength="20" />
</div>
<div class="col-3">
<q-select @input="resetSearch" filled v-model="msg.StuType" dense clearable :options="customTypeList"
option-label="Name" option-value="Id" emit-value map-options label="客户类型" />
</div>
<div class="col-3">
<q-select @input="resetSearch" dense filled v-model="msg.StuGuestState" :options="customState" option-label="Name"
option-value="Id" emit-value map-options label="客户状态" clearable />
</div>
<div class="col-3">
<q-select @input="resetSearch" dense v-model="msg.IsQueryMyStu" :options="isMyStuList" filled use-input
label="是否我协助的" option-label="Name" option-value="Id" ref="CustomerName" class="col-6" emit-value
map-options >
</q-select>
</div>
<div class="col-3">
<q-select @input="resetSearch" dense filled option-value="Id" option-label="Name" v-model="msg.Q_EnrollState"
:options="FTypeList" emit-value map-options label="报名状态" />
</div>
<div class="col-3">
<q-select @input="resetSearch" dense filled option-value="Id" option-label="Name" v-model="msg.BelongType"
:options="BelongTypeList" emit-value map-options label="归属类型" />
</div>
</div>
</div>
<div class="page-content">
<q-table :pagination="pageMsg" :loading="loading" no-data-label="暂无相关数据" flat
class="sticky-right-column-table sticky-tow-column-table" separator="none"
:data="dataList" :columns="columns" row-key="StuId" hide-bottom>
<template v-slot:body-cell-StuName="props">
<q-td :props="props">
<div class="text-blue cursor-pointer" @click="getStuRight(props.row)">
{{ props.value }}
</div>
</q-td>
</template>
<template v-slot:body-cell-EnrollState="props">
<q-td :props="props">
<q-badge :color="props.value == 1 ? 'negative' : 'primary'" :label="props.value == 1 ? '已报名' : '未成交'" />
</q-td>
</template>
<template v-slot:body-cell-AssistList="props">
<q-td auto-width :props="props">
<template v-if="props.row.AssistList">
<template v-if="props.row.AssistList.length==1">
{{props.row.AssistList[0].AssistName}}
</template>
<template v-if="props.row.AssistList.length>1">
{{props.row.AssistList[0].AssistName}}
<span class="stulistNum">
{{props.row.AssistList.length}}
<q-popup-proxy>
<q-banner>
<div style="max-height:600px;overflow-y:auto;">
<table class="stuListTable" style="border-collapse:collapse;">
<tr>
<th>角色</th>
<th>协同人</th>
</tr>
<tr v-for="(sItem,sIndex) in props.row.AssistList" style="border-bottom:1px dashed #d1d1d1;" :key="sIndex">
<td>{{sItem.AssistTypeName}}</td>
<td>{{sItem.AssistName}}</td>
</tr>
</table>
</div>
</q-banner>
</q-popup-proxy>
</span>
</template>
<template v-if="props.row.AssistList.length==0">
</template>
</template>
</q-td>
</template>
<!-- <template v-slot:body-cell-CustomerName="props">
<q-td>
<span v-if="props.row.BelongType!=3">{{props.row.CustomerName}}</span>
</q-td>
</template> -->
</q-table>
</div>
<q-pagination class="full-width justify-end" v-model="msg.pageIndex" color="primary" :max="PageCount"
:input="true" @input="changePage" />
<studentRight-form
v-if="isShowStuRight"
:isJudgeTrans="isJudgeTrans"
:BelongType="BelongType"
:save-obj="stuOption"
@close="closeStuForm"
@success="getList"
@reload="getList"
>
</studentRight-form>
</div>
</template>
<script>
import {
getStudentConsultPageList,
} from '../../api/studyabroad/index'
import {
queryStuStageList,
GetStudentTypeList,
} from "../../api/school/index";
import studentRightForm from "../../components/school/student/studentRight-form";
// import studentRightForm from "../../c/studentRight-form";
export default {
meta: {
title: "客户咨询"
},
props: {},
components: {
studentRightForm
},
data() {
return {
msg: {
pageIndex: 1,
pageSize: 12,
rowsPerPage: 12,
StuName: "",
StuRealMobile:'',
QQ:'',
WeChatNo:'',
StuType:'',//学生类型
StuGuestState:'',//状态
BelongType:'1',//归属类型(1-全部,2-我负责的,3-我协同的)
Q_EnrollState:'0',//报名状态 1已报名 2未成交 0不限
IsQueryMyStu:'-1',
},
loading: false,
dataList: [], //列表数据
PageCount:0,
customTypeList: [], //客户类型
customState: [],
isMyStuList:[{Id:'-1',Name:'不限'},{Id:'1',Name:'是'},{Id:'0',Name:'否'},],
FTypeList:[{Id:'0',Name:'不限'},{Id:'1',Name:'已报名'},{Id:'2',Name:'未成交'},],
BelongTypeList:[{Id:'1',Name:'全部'},{Id:'2',Name:'我负责的'},{Id:'3',Name:'我协同的'},],
dateArray: [], //日期数组
columns: [{
name: "StuName",
label: "学生",
field: "StuName",
align: "left"
},
{
name: "StuBirthStr",
required: true,
label: "生日",
field: row => row.StuBirthStr
},
{
name: "StuRealMobile",
label: "电话",
field: "StuRealMobile",
align: "left"
},
{
name: "StuAddress",
label: "地址",
field: "StuAddress",
align: "left"
},
{
name: "StuChannelName",
label: "渠道来源",
field: "StuChannelName",
align: "left"
},
{
name: "EnrollState",
label: "状态",
field: "EnrollState",
align: "left"
},
{
name: "CourseName",
label: "报名课程",
field: "CourseName",
align: "left"
},
{
name: "ConsultDate",
label: "咨询时间",
field: "ConsultDate",
align: "left"
},
{
name: "PlanPrice",
label: "规划课程及报价",
field: "PlanPrice",
align: "left"
},
{
name: "BaseCondition",
label: "基本情况",
field: "BaseCondition",
align: "left"
},
{
name: "DemandPoint",
label: "需求点",
field: "DemandPoint",
align: "left"
},
{
name: "ResistPoint",
label: "抗拒点",
field: "ResistPoint",
align: "left"
},
{
name: "ConsultingResults",
label: "咨询结果",
align: "left",
field: "ConsultingResults"
},
{
name: "JapanBaseInfo",
label: "日语基础",
field: "JapanBaseInfo",
align: "left"
},
{
name: "FUTime",
label: "跟进日期",
field: "FUTime",
align: "left"
},
{
name: "FURemark",
label: "跟进备注",
field: "FURemark",
align: "left"
},
],
stuOption: null,
BelongType: 1,
isShowStuRight:false,
isJudgeTrans:1,
}
},
created() { },
mounted() {
this.getList(); //获取规则
this.getStuStageList()
this.getCustomTypeList()
},
methods: {
resetSearch() {
this.msg.pageIndex = 1;
this.getList();
},
//翻页
changePage(val) {
this.msg.pageIndex = val;
this.getList()
},
getList() {
this.loading = true;
let msg = JSON.parse(JSON.stringify(this.msg))
if(msg.StuType=='' || msg.StuType==null){
msg.StuType = 0
}
if(msg.StuGuestState=='' || msg.StuGuestState==null){
msg.StuGuestState = 0
}
getStudentConsultPageList(msg).then(res => {
this.loading = false;
this.dataList = res.Data.PageData;
this.PageCount = res.Data.PageCount;
})
.catch(() => {
this.loading = false;
});
},
//获取客户类型
getCustomTypeList() {
GetStudentTypeList().then(res => {
if (res.Code == 1) {
this.customTypeList = res.Data;
}
})
},
//获取客户阶段列表
getStuStageList() {
queryStuStageList().then(res => {
this.customState = res.Data;
});
},
//点击学生姓名弹出
getStuRight(obj) {
if (obj) {
this.stuOption = obj;
this.BelongType = obj.BelongType;
}
this.isShowStuRight = true;
},
closeStuForm() {
this.isShowStuRight = false;
},
},
}
</script>
<style lang="sass">
@import url('~assets/css/table.sass')
</style>
<style scoped>
/deep/.el-input__inner,
/deep/.el-range-input {
background-color: transparent;
border: none;
}
</style>
<style>
@import "../financial/css/cssReset.css";
.baseSet_Title {
width: 120px !important;
padding: 18px 0 0 16px;
text-align: right;
}
.singeRowTable tr th {
border: 1px solid #d2d2d2;
}
td:first-child{background-color: #E6E6E6;position: sticky;left:0px;}
th:first-child{position: sticky;left:0px;}
</style>
<template>
<div class="page-body marketRules">
<div class="page-search row items-center">
<div class="col row wrap q-mr-lg q-col-gutter-md">
<div class="col-3">
<q-input @input="resetSearch" dense clearable filled v-model="msg.StuName" label="昵称" maxlength="20" />
</div>
<div class="col-3">
<q-input @input="resetSearch" dense clearable filled v-model="msg.StuRealMobile" label="电话" maxlength="20" />
</div>
<div class="col-3">
<q-input @input="resetSearch" dense clearable filled v-model="msg.QQ" label="QQ" maxlength="20" />
</div>
<div class="col-3">
<q-input @input="resetSearch" dense clearable filled v-model="msg.WeChatNo" label="微信号" maxlength="20" />
</div>
<div class="col-3">
<q-select @input="resetSearch" filled v-model="msg.StuType" dense clearable :options="customTypeList"
option-label="Name" option-value="Id" emit-value map-options label="客户类型" />
</div>
<div class="col-3">
<q-select @input="resetSearch" dense filled v-model="msg.StuGuestState" :options="customState" option-label="Name"
option-value="Id" emit-value map-options label="客户状态" clearable />
</div>
<div class="col-3">
<q-select @input="resetSearch" dense v-model="msg.IsQueryMyStu" :options="isMyStuList" filled use-input
label="是否查询我的学员" option-label="Name" option-value="Id" ref="CustomerName" class="col-6" emit-value
map-options >
</q-select>
</div>
<div class="col-3">
<q-select @input="resetSearch" dense filled option-value="Id" option-label="Name" v-model="msg.Q_FType"
:options="FTypeList" emit-value map-options label="跟进类型" />
</div>
<div class="col-3">
<q-field filled dense>
<template v-slot:control>
<el-date-picker v-model="dateArray" size="mini" @change="resetSearch" value-format="yyyy-MM-dd"
type="daterange" style="border:none;" range-separator="至" start-placeholder="开始时间"
end-placeholder="结束时间" />
</template>
</q-field>
</div>
</div>
</div>
<div class="col row wrap q-gutter-x-md" v-if="dataList.Stat">
<div class="col stics">
<span class="stics-name">学生总数</span>
<span>{{dataList.Stat.StuTNum?dataList.Stat.StuTNum:0}}人</span>
</div>
<div class="col stics">
<span class="stics-name">续费数量</span>
<span>{{dataList.Stat.RenewNum?dataList.Stat.RenewNum:0}}人</span>
</div>
<div class="col stics">
<span class="stics-name">新生数量</span>
<span style="color: #F72E52">{{dataList.Stat.NewNum?dataList.Stat.NewNum:0}}人</span>
</div>
<div class="col stics">
<span class="stics-name">学习中数量</span>
<span style="color:#2961FE;">{{dataList.Stat.StudyNum?dataList.Stat.StudyNum:0}}人</span>
</div>
<div class="col stics">
<span class="stics-name">毕业数量</span>
<span>{{dataList.Stat.GraduateNum?dataList.Stat.GraduateNum:0}}人</span>
</div>
<div class="col stics">
<span class="stics-name">停课数量</span>
<span>{{dataList.Stat.SuspendNum?dataList.Stat.SuspendNum:0}}人</span>
</div>
<div class="col stics">
<span class="stics-name">退学数量</span>
<span>{{dataList.Stat.DropOutNum?dataList.Stat.DropOutNum:0}}人</span>
</div>
</div>
<div style="width: 100%;margin-top: 20px">
<div style="width: 100%;overflow-x: auto;" >
<table
class="po_content singeRowTable"
style="border:1px solid #E6E6E6;"
cellspacing="0"
cellpadding="0"
v-loading="loading"
>
<tr>
<th width="120" rowspan="2" style="min-width: 120px;z-index: 999;">学生</th>
<th width="120" rowspan="2" style="min-width: 120px;">电话</th>
<th width="100" rowspan="2" style="min-width: 100px;">合同时间</th>
<th width="200" rowspan="2" style="min-width: 200px;">课程</th>
<th width="80" rowspan="2" style="min-width: 80px;">基础</th>
<th width="100" rowspan="2" style="min-width: 100px;">生日</th>
<th width="100" rowspan="2" style="min-width: 100px;">状态</th>
<th width="500" colspan="3" style="min-width: 500px;" v-for=" ( item , index ) in RListlength " :key = 'index'>
第{{index+1}}个月
</th>
</tr>
<tr >
<th v-for=" ( item , index ) in titlelist " :key = 'index' :width="item.Id==1?100:200" >{{item.Name}}</th>
</tr>
<tr v-for=" ( item , index ) in dataList.RList " :key="index" v-if='dataList.RList && dataList.RList.length>0'>
<td style=" border: 1px solid #d2d2d2;">
<span>{{ item.StuName }}</span>
</td>
<td>
<span>{{ item.StuTel }}</span>
</td>
<td>
<span>{{ item.ContractSTime }}</span>
</td>
<td>
<span>{{ item.CourseName }}</span>
</td>
<td>
<span>{{ item.JapanBaseInfo }}</span>
</td>
<td>
<span>{{ item.StuBirthStr }}</span>
</td>
<td>
<span>{{ item.StuGuestStateName }}</span>
</td>
<td v-for=" ( x , y ) in titlelist " :key="y" :style="{'background':x.Id==1 && item.MonthList[x.index] && (item.MonthList[x.index].IsRenew==1 || item.MonthList[x.index].IntroductionNum>0)?'red':'#FFF',
'color':x.Id==1 && item.MonthList[x.index] && (item.MonthList[x.index].IsRenew==1 || item.MonthList[x.index].IntroductionNum>0)?'#FFF':'#111'
}">
<div v-if="item.MonthList[x.index]">
<div v-if="x.Id==1" >
<span>{{item.MonthList[x.index].Month}}/</span>
<span v-if="item.MonthList[x.index].IsRenew==1"></span>
<span v-if="item.MonthList[x.index].IsRenew==2"></span>
<span>/{{item.MonthList[x.index].IntroductionNum}}</span>
</div>
<div v-if="x.Id==2">
<span v-if="item.MonthList[x.index].TeacherTime">{{item.MonthList[x.index].TeacherTime+':'}}</span>
<span v-if="item.MonthList[x.index].Teacher" v-html="item.MonthList[x.index].Teacher"></span>
</div>
<div v-if="x.Id==3">
<span v-if="item.MonthList[x.index].ConsultantTime">{{item.MonthList[x.index].ConsultantTime+':'}}</span>
<span v-if="item.MonthList[x.index].Consultant" v-html="item.MonthList[x.index].Consultant"></span>
</div>
</div>
</td>
</tr>
</table>
</div>
<div v-if='!dataList.RList||(dataList.RList && dataList.RList.length==0)'
style="width: 100%;border:1px solid #E6E6E6;display: flex;align-items: center;justify-content: center;height: 60px;">
暂无数据
</div>
<q-pagination class="full-width justify-end" v-model="msg.pageIndex" color="primary" :max="PageCount"
:input="true" @input="changePage" />
</div>
</div>
</template>
<script>
import {
getStudentFollowUpPageList,
} from '../../api/studyabroad/index'
import {
queryStuStageList,
GetStudentTypeList,
} from "../../api/school/index";
export default {
meta: {
title: "学员跟踪"
},
props: {},
components: {
},
data() {
return {
msg: {
pageIndex: 1,
pageSize: 12,
rowsPerPage: 12,
StuName: "",
StuRealMobile:'',
QQ:'',
WeChatNo:'',
StuType:'',//学生类型
StuGuestState:'',//状态
IsQueryMyStu:'-1',//是否查询我的学员 1是 0否
SFTime:'',
EFTime:'',
Q_FType:'-1',//跟进类型 1范围内有跟进记录 2范围内没有跟进记录
},
loading: false,
dataList: [], //列表数据
PageCount:0,
customTypeList: [], //客户类型
customState: [],
isMyStuList:[{Id:'-1',Name:'不限'},{Id:'1',Name:'是'},{Id:'0',Name:'否'},],
FTypeList:[{Id:'-1',Name:'不限'},{Id:'1',Name:'范围内有跟进记录'},{Id:'2',Name:'范围内没有跟进记录 '},],
dateArray: [], //日期数组
RListlength:0,
titlelist:[]
}
},
created() { },
mounted() {
this.getList(); //获取规则
this.getStuStageList()
this.getCustomTypeList()
},
methods: {
resetSearch() {
this.msg.pageIndex = 1;
this.getList();
},
//翻页
changePage(val) {
this.msg.pageIndex = val;
this.getList()
},
getList() {
this.loading = true;
let msg = JSON.parse(JSON.stringify(this.msg))
if (this.dateArray && this.dateArray.length > 0) {
msg.StartTime = this.dateArray[0];
msg.EndTime = this.dateArray[1];
} else {
msg.StartTime = "";
msg.EndTime = "";
}
if(msg.StuType=='' || msg.StuType==null){
msg.StuType = 0
}
if(msg.StuGuestState=='' || msg.StuGuestState==null){
msg.StuGuestState = 0
}
getStudentFollowUpPageList(msg).then(res => {
this.loading = false;
this.RListlength = 1;
this.titlelist=[{Name:'月份/续费/介绍数量',Id:1,index:0},{Name:'教师跟进',Id:2,index:0},{Name:'顾问跟进',Id:3,index:0},];
this.dataList = res.Data.PageData;
this.PageCount = res.Data.PageCount;
if(this.dataList && this.dataList.RList&& this.dataList.RList.length>0){
this.dataList.RList.forEach(x=>{
if(x.MonthList.length> this.RListlength){
this.RListlength = x.MonthList.length
}
})
}
this.titlelist=[];
for(let i=0;i<this.RListlength;i++){
let obj=[{Name:'月份/续费/介绍数量',Id:1,index:i},{Name:'教师跟进',Id:2,index:i},{Name:'顾问跟进',Id:3,index:i},]
this.titlelist = [...this.titlelist, ...obj]
}
})
.catch(() => {
this.loading = false;
});
},
//获取客户类型
getCustomTypeList() {
GetStudentTypeList().then(res => {
if (res.Code == 1) {
this.customTypeList = res.Data;
}
})
},
//获取客户阶段列表
getStuStageList() {
queryStuStageList().then(res => {
this.customState = res.Data;
});
},
},
}
</script>
<style lang="sass">
@import url('~assets/css/table.sass')
</style>
<style scoped>
/deep/.el-input__inner,
/deep/.el-range-input {
background-color: transparent;
border: none;
}
.stics {
padding: 10px 20px;
background: #DDDEE0;
border-radius: 4px;
font-size: 13px;
color: #000000;
font-weight: bold
}
.stics .stics-name {
color: #2D2D2D;
font-weight: 600;
margin-right: 10px
}
</style>
......@@ -1035,6 +1035,16 @@ const routes = [{
component: () =>
import("pages/sale/AudiopaymentDetail.vue")
},
{
path: "/sale/studentTracking", //学员跟踪分页列表
component: () =>
import("pages/sale/studentTracking.vue")
},
{
path: "/sale/guestConsultation", //客人咨询分页列表
component: () =>
import("pages/sale/guestConsultation.vue")
},
{
path: "/activity/activeType", //活动 活动类型
component: () =>
......
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