|
@@ -0,0 +1,459 @@
|
|
|
+<script>
|
|
|
+import { defineComponent } from "vue";
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ beforeRouteEnter(to, from, next) {
|
|
|
+ // 从续约客户列表进来才使用 renewalTab
|
|
|
+ if(from.path != '/contractCustomlist'){
|
|
|
+ sessionStorage.removeItem('renewalTab')
|
|
|
+ }
|
|
|
+ next()
|
|
|
+ },
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import _ from "lodash"
|
|
|
+import {ref,computed} from "vue"
|
|
|
+import { useRouter} from 'vue-router';
|
|
|
+import DatePicker from 'vue-datepicker-next';
|
|
|
+import { InfoFilled,ArrowDown,ArrowUp } from '@element-plus/icons-vue'
|
|
|
+
|
|
|
+import { dataMainInterface } from '@/api/api.js';
|
|
|
+import {createdHook,dataHook,computedHook,functionHook} from './hook'
|
|
|
+
|
|
|
+const $router = useRouter()
|
|
|
+const {dataLoading,default_tab,select_date,totalGroupArr,datalist,tableTheadColumns,staticTabs}=dataHook()
|
|
|
+const {Role,activeTab}=computedHook()
|
|
|
+const {filterTableData,switchTab,dateChange,changeTabHandle}=functionHook()
|
|
|
+
|
|
|
+const tipMap=new Map([
|
|
|
+ ['未续约','之前是正式客户,现在是冻结或流失状态的客户'],
|
|
|
+ ['续约跟进','之前是正式客户,现在是试用状态且未经历过冻结或流失状态的客户'],
|
|
|
+ ['到期','合同到期时间在统计时间段内的客户'],
|
|
|
+ ['续约','续约申请审批通过时间在所选时间段内的客户'],
|
|
|
+ ['续约异常','合同到期后两个月内未签约 '],
|
|
|
+ ['异常率','异常率=当期续约异常客户总数/截止当期系统中存量客户总数']
|
|
|
+])
|
|
|
+const notRenewNumAll=ref(0) // 未续约总合计
|
|
|
+const renewFollowNumAll=ref(0) // 续约跟进总合计
|
|
|
+const UnusualRateArr=ref([])
|
|
|
+
|
|
|
+const contractTableThead=computed(()=>{
|
|
|
+ if(['周度统计表','月度统计表'].includes(default_tab.value)){
|
|
|
+ return tableTheadColumns.value
|
|
|
+ }
|
|
|
+ return activeTab.value.tabName !== 'QY'?['到期','续约','续约异常']:['到期','续约']
|
|
|
+})
|
|
|
+
|
|
|
+const getTableData=()=>{
|
|
|
+ dataLoading.value = false;
|
|
|
+ dataMainInterface.renewalCustomStatistic({
|
|
|
+ DataType: default_tab.value === '周度统计表' ? 'week' : default_tab.value === '月度统计表' ? 'month' : 'time_interval',
|
|
|
+ StartDate: select_date.value ? select_date.value[0] : '',
|
|
|
+ EndDate: select_date.value ? select_date.value[1] : '',
|
|
|
+ ProductId:activeTab.value.productionId
|
|
|
+ }).then(res => {
|
|
|
+ const { Data,Ret } = res;
|
|
|
+ if(Ret !== 200) return
|
|
|
+ //总合计数据处理
|
|
|
+ totalGroupArr.value = filterTableData(Data.CompanyRenewRecordNumList,{},'renew');
|
|
|
+ notRenewNumAll.value = Data.CompanyRenewRecordNumList[0].NotRenewNum
|
|
|
+ renewFollowNumAll.value = Data.CompanyRenewRecordNumList[0].RenewFollowNum
|
|
|
+ // 异常率处理
|
|
|
+ UnusualRateArr.value= Data.CompanyRenewRecordNumList||[]
|
|
|
+ //处理数据结构
|
|
|
+ let data = []
|
|
|
+ if(activeTab.value.productionId ==1){
|
|
|
+ // FICC
|
|
|
+ data = _.cloneDeep(Data.List).sort((a,b) => b.Item.length - a.Item.length);
|
|
|
+ //data.push({Item: [], GroupId: 37, Name: "共享客户组", CompanyRenewRecordNumList: []})
|
|
|
+ }else{
|
|
|
+ data=_.cloneDeep(Data.List)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ data.forEach(item => {
|
|
|
+ item.showDetail=false
|
|
|
+ let groupDataArr = filterTableData(item.CompanyRenewRecordNumList,{
|
|
|
+ rs_name: item.Name + '合计'
|
|
|
+ },'renew');
|
|
|
+ // 将 未续约 和 续约跟进 加入
|
|
|
+ if(item.CompanyRenewRecordNumList[0]){
|
|
|
+ groupDataArr.unshift({
|
|
|
+ key: '未续约',
|
|
|
+ value: item.CompanyRenewRecordNumList[0].NotRenewNum,
|
|
|
+ ids: item.CompanyRenewRecordNumList[0].NotRenewIds,
|
|
|
+ rs_name: item.Name + '合计'
|
|
|
+ },{
|
|
|
+ key: '续约跟进',
|
|
|
+ value: item.CompanyRenewRecordNumList[0].RenewFollowNum,
|
|
|
+ ids: item.CompanyRenewRecordNumList[0].RenewFollowIds,
|
|
|
+ rs_name: item.Name + '合计'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ item.subGroupArr=groupDataArr
|
|
|
+
|
|
|
+ item.Item && item.Item.forEach(sub_item => {
|
|
|
+
|
|
|
+ let dataArr = filterTableData(sub_item.CompanyRenewRecordNumList,{
|
|
|
+ rs_name : sub_item.Name,
|
|
|
+ },'renew')
|
|
|
+ // 将 未续约 和 续约跟进 加入
|
|
|
+ dataArr.unshift({
|
|
|
+ key: '未续约',
|
|
|
+ value: sub_item.CompanyRenewRecordNumList[0].NotRenewNum,
|
|
|
+ ids: sub_item.CompanyRenewRecordNumList[0].NotRenewIds,
|
|
|
+ rs_name : sub_item.Name,
|
|
|
+ },{
|
|
|
+ key: '续约跟进',
|
|
|
+ value: sub_item.CompanyRenewRecordNumList[0].RenewFollowNum,
|
|
|
+ ids: sub_item.CompanyRenewRecordNumList[0].RenewFollowIds,
|
|
|
+ rs_name : sub_item.Name,
|
|
|
+ })
|
|
|
+ sub_item.dataArr=dataArr
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ datalist.value = data.filter(i=>i.CompanyRenewRecordNumList.length);
|
|
|
+ dataLoading.value = true;
|
|
|
+ // const dynamic_width = {
|
|
|
+ // '周度统计表': '5%',
|
|
|
+ // '月度统计表': '5%',
|
|
|
+ // }
|
|
|
+ // // console.log(this.datalist,'this.datalist');
|
|
|
+ // this.$nextTick(() => {
|
|
|
+ // this.dataLoading = true;
|
|
|
+ // $('table').find('td').css({ width: dynamic_width[this.default_tab]?dynamic_width[this.default_tab]:'20%'})
|
|
|
+ // $('table').find('.thead-rs').css({ width: dynamic_width[this.default_tab] ? dynamic_width[this.default_tab] : '120px' })
|
|
|
+ // $('table').find('.thead-rs-typeTwo').css({
|
|
|
+ // width: dynamic_width[this.default_tab] ? dynamic_width[this.default_tab] : '20%' ,
|
|
|
+ // backgroundColor:dynamic_width[this.default_tab] ? "#fff" :"#F0F2F5"})
|
|
|
+ // $('table').find('.head-column').css({ width: dynamic_width[this.default_tab] ? dynamic_width[this.default_tab] : '20%' })
|
|
|
+ // })
|
|
|
+ })
|
|
|
+}
|
|
|
+/* 进入列表 */
|
|
|
+const goList=({value,rs_name,ids,key},index, parent)=>{
|
|
|
+ if(!parent.length || !value) return
|
|
|
+ let column_title = getColumnTitle(index);
|
|
|
+ let title=''
|
|
|
+ if(['未续约','续约跟进'].includes(key)){
|
|
|
+ title = encodeURIComponent(`${rs_name}/${key}`);
|
|
|
+ }else{
|
|
|
+ title = encodeURIComponent(`${column_title}/${rs_name}/${key}`);
|
|
|
+ }
|
|
|
+ sessionStorage.setItem('renewalTab',activeTab.value.tabName)
|
|
|
+ const{href}=$router.resolve({
|
|
|
+ name: 'contractCustomlist',
|
|
|
+ query: {
|
|
|
+ ids: encodeURIComponent(ids),
|
|
|
+ title
|
|
|
+ }
|
|
|
+ })
|
|
|
+window.open(href,'_blank')
|
|
|
+}
|
|
|
+/* 获取数据对应表头 */
|
|
|
+const getColumnTitle=(index)=>{
|
|
|
+ let title = '';
|
|
|
+
|
|
|
+ if(['周度统计表','月度统计表'].includes(default_tab.value)) {
|
|
|
+ title = [2,3,4].includes(index)
|
|
|
+ ? tableTheadColumns.value[0]
|
|
|
+ : [5,6,7].includes(index)
|
|
|
+ ? tableTheadColumns.value[1]
|
|
|
+ : [8,9,10].includes(index)
|
|
|
+ ? tableTheadColumns.value[2]
|
|
|
+ : [11,12,13].includes(index)
|
|
|
+ ? tableTheadColumns.value[3]
|
|
|
+ : [14,15,16].includes(index)
|
|
|
+ ? tableTheadColumns.value[4]
|
|
|
+ : [17,18,19].includes(index)
|
|
|
+ ? tableTheadColumns.value[5]
|
|
|
+ : '';
|
|
|
+ } else {
|
|
|
+ title = default_tab.value || `${select_date.value[0]}~${select_date.value[1]}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ return title
|
|
|
+}
|
|
|
+
|
|
|
+// start
|
|
|
+getTableData()
|
|
|
+createdHook()
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="statistic-container" ref="reference">
|
|
|
+ <div class="custom-tab-box" v-if="Role==='admin'">
|
|
|
+ <div class="custom-tab" :class="activeTab.tabName =='FICC' && 'activeTab'" @click="switchTab('FICC',getTableData)">
|
|
|
+ FICC
|
|
|
+ </div>
|
|
|
+ <div class="custom-tab" :class="activeTab.tabName =='QY' && 'activeTab'" @click="switchTab('QY',getTableData)">
|
|
|
+ 权益
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="frequency-cont">
|
|
|
+ <ul class="frequency-ul">
|
|
|
+ <li v-for="tab in staticTabs" :key="tab" :class="{act: tab=== default_tab}" @click="changeTabHandle(tab,getTableData)">{{ tab }}</li>
|
|
|
+ </ul>
|
|
|
+ <date-picker
|
|
|
+ v-model:value="select_date"
|
|
|
+ type="date"
|
|
|
+ range
|
|
|
+ value-type="format"
|
|
|
+ :clearable="false"
|
|
|
+ @change="dateChange(getTableData)"
|
|
|
+ placeholder="请选择统计时间"/>
|
|
|
+ </div>
|
|
|
+ <div class="table-cont" v-show="dataLoading">
|
|
|
+ <!-- <table>
|
|
|
+ <thead>
|
|
|
+ <tr>
|
|
|
+ <td rowspan="2" class="thead-rs">组别</td>
|
|
|
+ <td rowspan="2" class="thead-rs">销售</td>
|
|
|
+ <td rowspan="2" class="thead-rs-typeTwo">
|
|
|
+ 未续约
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ :content="tipMap.get('未续约')"
|
|
|
+ v-if="['周度统计表'].includes(default_tab)"
|
|
|
+ >
|
|
|
+ <i class="el-icon-info"/>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ <td rowspan="2" class="thead-rs-typeTwo">
|
|
|
+ 续约跟进
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ :content="tipMap.get('续约跟进')"
|
|
|
+ v-if="['周度统计表'].includes(default_tab)"
|
|
|
+ >
|
|
|
+ <i class="el-icon-info"/>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ <td
|
|
|
+ :colspan="['周度统计表','月度统计表'].includes(default_tab) ? 2 : 1"
|
|
|
+ v-for="item in contractTableThead"
|
|
|
+ :key="item"
|
|
|
+ class="head-column"
|
|
|
+ >
|
|
|
+ {{item}}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr v-if="['周度统计表'].includes(default_tab)">
|
|
|
+ <template v-for="(item,index) in new Array(6).fill('')">
|
|
|
+ <td :key="index+'_0'">
|
|
|
+ 到期
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ v-if="index === 0"
|
|
|
+ :content="tipMap.get('到期')"
|
|
|
+ >
|
|
|
+ <i class="el-icon-info"/>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ <td :key="index+'_1'">
|
|
|
+ 续约
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ v-if="index === 0"
|
|
|
+ :content="tipMap.get('续约')"
|
|
|
+ >
|
|
|
+ <i class="el-icon-info"/>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ </template>
|
|
|
+ </tr>
|
|
|
+ <tr v-else-if="['月度统计表'].includes(default_tab)">
|
|
|
+ <template v-for="(item,index) in new Array(6).fill('')">
|
|
|
+ <td :key="index+'_0'">到期</td>
|
|
|
+ <td :key="index+'_1'">续约</td>
|
|
|
+ </template>
|
|
|
+ </tr>
|
|
|
+ </thead>
|
|
|
+ </table> -->
|
|
|
+ <div class="table-body-wrapper">
|
|
|
+ <table>
|
|
|
+ <thead>
|
|
|
+ <tr>
|
|
|
+ <td rowspan="2" class="thead-rs">组别</td>
|
|
|
+ <td rowspan="2" class="thead-rs">销售</td>
|
|
|
+ <td rowspan="2" class="thead-rs-typeTwo">
|
|
|
+ 未续约
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ :content="tipMap.get('未续约')"
|
|
|
+ >
|
|
|
+ <el-icon :size="14" style="vertical-align: text-top;"><InfoFilled /></el-icon>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ <td rowspan="2" class="thead-rs-typeTwo">
|
|
|
+ 续约跟进
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ :content="tipMap.get('续约跟进')"
|
|
|
+ >
|
|
|
+ <el-icon :size="14" style="vertical-align: text-top;"><InfoFilled /></el-icon>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ <td
|
|
|
+ :colspan="['周度统计表','月度统计表'].includes(default_tab) ? activeTab.tabName !== 'QY'? 3:2 : 1"
|
|
|
+ v-for="item in contractTableThead"
|
|
|
+ :key="item"
|
|
|
+ class="head-column"
|
|
|
+ >
|
|
|
+ {{item}}
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ v-if="!['周度统计表','月度统计表'].includes(default_tab)"
|
|
|
+ :content="tipMap.get(item)"
|
|
|
+ >
|
|
|
+ <el-icon :size="14" style="vertical-align: text-top;"><InfoFilled /></el-icon>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr v-if="['周度统计表','月度统计表'].includes(default_tab)">
|
|
|
+ <template v-for="(item,index) in new Array(6).fill('')" :key="index">
|
|
|
+ <td>
|
|
|
+ 到期
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ v-if="index === 0"
|
|
|
+ :content="tipMap.get('到期')"
|
|
|
+ >
|
|
|
+ <el-icon :size="14" style="vertical-align: text-top;"><InfoFilled /></el-icon>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ 续约
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ v-if="index === 0"
|
|
|
+ :content="tipMap.get('续约')"
|
|
|
+ >
|
|
|
+ <el-icon :size="14" style="vertical-align: text-top;"><InfoFilled /></el-icon>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ <td v-if="activeTab.tabName !== 'QY'">
|
|
|
+ 续约异常
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ v-if="index === 0"
|
|
|
+ :content="tipMap.get('续约异常')"
|
|
|
+ >
|
|
|
+ <el-icon :size="14" style="vertical-align: text-top;"><InfoFilled /></el-icon>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ </template>
|
|
|
+ </tr>
|
|
|
+ </thead>
|
|
|
+ <tbody v-for="item in datalist" :key="item.Name">
|
|
|
+ <tr>
|
|
|
+ <td colspan="2" @click="item.showDetail=!item.showDetail">{{item.Name}}合计
|
|
|
+ <el-icon :size="14" style="vertical-align: text-top;" v-if="item.Item.length">
|
|
|
+ <ArrowUp v-show="item.showDetail" />
|
|
|
+ <ArrowDown v-show="!item.showDetail" />
|
|
|
+ </el-icon>
|
|
|
+ </td>
|
|
|
+ <td
|
|
|
+ v-for="(group_data,group_data_key) in item.subGroupArr"
|
|
|
+ :key="group_data_key"
|
|
|
+ :class="{link: item.Item.length}"
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ @click="goList(group_data,group_data_key,item.Item)"
|
|
|
+ >
|
|
|
+ {{ group_data.value !== 0 ? group_data.value : '' }}
|
|
|
+ </span>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <template v-if="item.Item.length">
|
|
|
+ <tr v-show="item.showDetail">
|
|
|
+ <td :rowspan="item.Item.length+1" class="thead-rs">{{item.Name}}</td>
|
|
|
+ </tr>
|
|
|
+
|
|
|
+ <tr v-for="rs in item.Item" :key="rs.AdminId" v-show="item.showDetail">
|
|
|
+ <td class="thead-rs">{{rs.Name}}</td>
|
|
|
+
|
|
|
+ <td
|
|
|
+ :class="['data-cell',{link: item.Item.length}]"
|
|
|
+ v-for="(data,data_key) in rs.dataArr"
|
|
|
+ :key="data_key"
|
|
|
+ >
|
|
|
+
|
|
|
+ <span
|
|
|
+ @click="goList(data,data_key,item.Item)"
|
|
|
+ v-if="Object.prototype.toString.call(data.value) === '[object Number]'"
|
|
|
+ >
|
|
|
+ {{ data.value !== 0 ? data.value : '' }}
|
|
|
+ </span>
|
|
|
+ </td>
|
|
|
+
|
|
|
+ </tr>
|
|
|
+ </template>
|
|
|
+ </tbody>
|
|
|
+
|
|
|
+ <tfoot>
|
|
|
+ <tr>
|
|
|
+ <td colspan="2">{{activeTab.tabSummationName}}</td>
|
|
|
+ <td>
|
|
|
+ <span>
|
|
|
+ {{ notRenewNumAll !== 0 ? notRenewNumAll : '' }}
|
|
|
+ </span>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <span>
|
|
|
+ {{ renewFollowNumAll !== 0 ? renewFollowNumAll : '' }}
|
|
|
+ </span>
|
|
|
+ </td>
|
|
|
+ <td v-for="(item,index) in totalGroupArr" :key="index">
|
|
|
+ <span>
|
|
|
+ {{ item.value !== 0 ? item.value : '' }}
|
|
|
+ </span>
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr v-if="activeTab.tabName !== 'QY'">
|
|
|
+ <td colspan="2">
|
|
|
+ <span>异常率</span>
|
|
|
+ <el-tooltip
|
|
|
+ effect="dark"
|
|
|
+ placement="top-start"
|
|
|
+ :content="tipMap.get('异常率')"
|
|
|
+ >
|
|
|
+ <el-icon :size="14" style="vertical-align: text-top;margin-left: 3px"><InfoFilled /></el-icon>
|
|
|
+ </el-tooltip>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <span></span>
|
|
|
+ </td>
|
|
|
+ <td>
|
|
|
+ <span></span>
|
|
|
+ </td>
|
|
|
+ <template v-if="['周度统计表','月度统计表'].includes(default_tab)">
|
|
|
+ <td v-for="(item,index) in UnusualRateArr" :key="index" colspan="3">{{item.UnusualRate}}</td>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <td colspan="3">{{UnusualRateArr[0].UnusualRate}}</td>
|
|
|
+ </template>
|
|
|
+ </tr>
|
|
|
+ </tfoot>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<style lang="scss" scoped>
|
|
|
+ @import './index.scss';
|
|
|
+
|
|
|
+</style>
|