Bladeren bron

存量客户统计、续约客户统计、续约异常统计、添加客户权限

hbchen 11 maanden geleden
bovenliggende
commit
12e1f21164

+ 2 - 0
index.html

@@ -9,5 +9,7 @@
   <body>
     <div id="app"></div>
     <script type="module" src="/src/main.js"></script>
+    <!-- echart cdn -->
+    <script type="text/javascript" src="https://lib.baomitu.com/echarts/5.0.2/echarts.min.js"></script>
   </body>
 </html>

+ 58 - 46
src/router/modules/sellerRoutes.js

@@ -30,18 +30,22 @@ export default [
 					title: "新增客户统计",
 				},
 			},
-			// {
-			// 	path: 'sellerStatisticStockcustom',
-			// 	component: () => import('@/views/dataReport_manage/statistic/stockCustom.vue'),
-			// 	name: '存量客户统计',
-			// 	hidden: false
-			// },
-			// {
-			// 	path: 'sellerStatisticContractcustom',
-			// 	component: () => import('@/views/dataReport_manage/statistic/contractCustom.vue'),
-			// 	name: '续约客户统计',
-			// 	hidden: false
-			// },
+			{
+				path: 'sellerStatisticStockcustom',
+				component: () => import('@/views/dataReport_manage/statistic/stockCustom.vue'),
+				name: 'sellerStatisticStockcustom',
+				meta: {
+					title: "存量客户统计",
+				},
+			},
+			{
+				path: 'sellerStatisticContractcustom',
+				component: () => import('@/views/dataReport_manage/statistic/contractCustom.vue'),
+				name: 'sellerStatisticContractcustom',
+				meta: {
+					title: "续约客户统计",
+				},
+			},
 			{
 				path: 'newCustomlist',
 				component: () => import('@/views/dataReport_manage/statistic/newCustomlist.vue'),
@@ -53,16 +57,17 @@ export default [
 				},
 				hidden: true
 			},
-			// {
-			// 	path: 'contractCustomlist',
-			// 	component: () => import('@/views/dataReport_manage/statistic/newCustomlist.vue'),
-			// 	name: '续约客户列表',
-			// 	meta: {
-			// 		pathFrom: 'sellerStatisticContractcustom',
-			// 		pathName: '续约客户统计'
-			// 	},
-			// 	hidden: true
-			// },
+			{
+				path: 'contractCustomlist',
+				component: () => import('@/views/dataReport_manage/statistic/newCustomlist.vue'),
+				name: 'contractCustomlist',
+				meta: {
+					pathFrom: 'sellerStatisticContractcustom',
+					pathName: '续约客户统计',
+					title:'续约客户列表'
+				},
+				hidden: true
+			},
 			// {
 			// 	path: 'sellerTodoTask',
 			// 	component: () => import('@/views/dataReport_manage/statistic/todoTask.vue'),
@@ -113,8 +118,10 @@ export default [
 			// {
 			// 	path:"ficcProductStatistic",
 			// 	component: () => import('@/views/dataReport_manage/statistic/ficcProduct.vue'),
-			// 	name: '分产品阅读统计',
-			// 	hidden: false
+			// 	name: 'ficcProductStatistic',
+			// 	meta: {
+			// 		title: "分产品阅读统计",
+			// 	}
 			// },
 			// {
 			// 	path: 'ficcProductlist',
@@ -126,28 +133,33 @@ export default [
 			// 	},
 			// 	hidden: true
 			// },
-			// {
-			// 	path:"receiveCompanyPermission",
-			// 	name: '添加客户权限',
-			// 	component: () => import('@/views/custom_manage/saleAuthManage.vue'),
-			// 	hidden: false,
-			// },
-			// {
-			// 	path:"abnormalRenewal",
-			// 	name: '续约异常统计',
-			// 	component: () => import('@/views/dataReport_manage/statistic/abnormalRenewal.vue'),
-			// 	hidden: false,
-			// },
-			// {
-			// 	path: 'abnormalRenewalCustomlist',
-			// 	component: () => import('@/views/dataReport_manage/statistic/newCustomlist.vue'),
-			// 	name: '续约异常客户列表',
-			// 	meta: {
-			// 		pathFrom: 'abnormalRenewal',
-			// 		pathName: '续约异常统计' 
-			// 	},
-			// 	hidden: true
-			// },
+			{
+				path:"receiveCompanyPermission",
+				name: 'receiveCompanyPermission',
+				component: () => import('@/views/dataReport_manage/saleAuthManage.vue'),
+				meta: {
+					title: "添加客户权限",
+				},
+			},
+			{
+				path:"abnormalRenewal",
+				name: 'abnormalRenewal',
+				component: () => import('@/views/dataReport_manage/statistic/abnormalRenewal.vue'),
+				meta: {
+					title: "续约异常统计",
+				},
+			},
+			{
+				path: 'abnormalRenewalCustomlist',
+				component: () => import('@/views/dataReport_manage/statistic/newCustomlist.vue'),
+				name: 'abnormalRenewalCustomlist',
+				meta: {
+					pathFrom: 'abnormalRenewal',
+					pathName: '续约异常统计',
+					title:'续约异常客户列表'
+				},
+				hidden: true
+			},
 		]
 	},
 ]

+ 6 - 4
src/views/business_trip_manage/businessApplication.vue

@@ -201,10 +201,12 @@ getApplication()
           </div>
         </template>
       </el-table-column>
-      <div slot="empty" class="table-noData">
-        <img src="~@/assets/img/cus_m/nodata.png">
-        <span>暂无数据</span>
-      </div>
+      <template #empty>
+        <div class="table-noData">
+          <img src="~@/assets/img/cus_m/nodata.png">
+          <span>暂无数据</span>
+        </div>
+      </template>
     </el-table>
     <!-- 页数选择器 -->
     <m-page

+ 6 - 4
src/views/business_trip_manage/businessApproval.vue

@@ -140,10 +140,12 @@ getApproveList()
           </div>
         </template>
       </el-table-column>
-      <div slot="empty" class="table-noData">
-        <img src="~@/assets/img/cus_m/nodata.png">
-        <span>暂无数据</span>
-      </div>
+      <template #empty>
+        <div class="table-noData">
+          <img src="~@/assets/img/cus_m/nodata.png">
+          <span>暂无数据</span>
+        </div>
+      </template>
     </el-table>
     <!-- 页数选择器 -->
     <m-page

+ 161 - 0
src/views/dataReport_manage/components/abnormalRenewalChart.vue

@@ -0,0 +1,161 @@
+<script setup>
+import {ref,nextTick} from "vue"
+import moment from "moment"
+
+import { dataMainInterface } from '@/api/api.js';
+
+const emits=defineEmits(['close'])
+
+const date=ref('')
+const myChart=ref(null)
+
+const getData=async()=>{
+    const res=await dataMainInterface.unusualRenewalCustomStatisticChartData({
+        StartDate:date.value[0],
+        EndDate:date.value[1]
+    })
+    if(res.Ret===200){
+        nextTick(()=>{
+            renderChart(res.Data)
+        })
+    }
+}
+const handleDateChange=()=>{
+    getData()
+}
+const handleClose=()=>{
+    emits('close')
+}
+
+const chartBox=ref(null)
+const renderChart=(data)=>{
+    const arr=data.List||[]
+
+    const options={
+        legend: {
+            name: [],
+            icon:'circle',
+            left: 'center',
+        },
+        tooltip: {
+            formatter:function(params){
+                let str=`${params.name}<br>
+                <span style='display:inline-block;width:15px;height:15px;background:#FDB863;border-radius:100%'></span>
+                ${params.seriesName}&nbsp;&nbsp;${params.value}`
+
+                return str
+            }
+        },
+        title: {
+            text: '',
+        },
+        color: ['#FDB863'],
+        textStyle: {
+            fontSize: 12,
+        },
+        xAxis: {
+            type: '',
+            data: [],
+            // /* x轴文字 */
+            axisLabel: {
+                show: true,
+                rotate: '40', //字体倾斜
+                textStyle: {
+                    color: '#999', //更改坐标轴文字颜色
+                    fontSize: 12, //更改坐标轴文字大小
+                },
+            },
+        },
+        yAxis: {
+            type: 'value',
+            minInterval:1,
+            position: 'left',
+            name:'家',
+            splitLine:{
+                lineStyle:{
+                    type:'dotted'
+                }
+            }
+        },
+        series: [
+            {
+                data:[],
+                name:'续约异常客户合计',
+                type:'bar',
+                yAxisIndex: 0,
+            }
+        ],
+    }
+
+    arr.forEach(item => {
+        options.xAxis.data.push(item.Date)
+        options.series[0].data.push(item.CompanyNum)
+    });
+
+    console.log(options);
+
+    const chart = chartBox.value;
+    if(chart){
+        nextTick(()=>{
+            if(!myChart.value){
+                myChart.value = echarts.init(chart);
+                myChart.value.setOption(options);
+            }else{
+                myChart.value.setOption(options,true);
+            }
+            
+        })
+    }
+}
+
+//start
+date.value=[moment().format('2023-01'),moment().format('YYYY-MM')]
+getData()
+</script>
+
+<template>
+    <div class="abnormal-renewal-chart-wrap">
+        <div class="top-wrap">
+            <el-date-picker
+                v-model="date"
+                type="monthrange"
+                range-separator="至"
+                start-placeholder="开始日期"
+                end-placeholder="结束日期"
+                :clearable="false"
+                value-format="YYYY-MM"
+                @change="handleDateChange"
+                style="max-width: 300px;"
+            />
+            <div style="color:#409EFF;cursor: pointer;" @click="handleClose">
+                <img src="~@/assets/img/icons/changeLang.png" alt="">
+                <span style="display:inline-block;position: relative;top:-3px;left:3px">数据表</span>
+            </div>
+        </div>
+        <div class="chart-main-wrap">
+            <h2 style="text-align:center;font-size:30px;margin:30px 0;">续约异常客户统计图</h2>
+            <div class="chart-box" ref="chartBox"></div>
+        </div>
+    </div>
+</template>
+
+<style lang="scss" scoped>
+.abnormal-renewal-chart-wrap{
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: #fff;
+    padding: 30px;
+    .top-wrap{
+        display: flex;
+        justify-content: space-between;
+    }
+    .chart-box{
+        margin: 0 auto;
+        width: 80%;
+        height: 500px;
+    }
+}
+</style>

+ 249 - 0
src/views/dataReport_manage/saleAuthManage.vue

@@ -0,0 +1,249 @@
+<script setup>
+import {ref} from "vue"
+import { QuestionFilled } from '@element-plus/icons-vue'
+import {ElMessage} from "element-plus"
+
+import { customInterence } from "@/api/api.js";
+
+const sales=ref("")
+const salesArr=ref([])
+const defaultSalesProps={
+  multiple: true,
+  label: "RealName",
+  children: "ChildrenList",
+  value: "AdminId",
+} //销售级联配置
+
+const search_txt=ref("")
+const tableColumns=[
+  {
+    label: "销售姓名",
+    key: "RealName",
+  },
+  {
+    label: "所属分组",
+    key: "DepartmentGroup",
+    minWidth: 220,
+  },
+  {
+    label: "状态",
+    key: "Enabled",
+  },
+]
+const tableData=ref([])
+const isShowloadding=ref(false)
+const page_no=ref(1)
+const pageSize=ref(10)
+const total=ref(1)
+
+const getTableData=async()=>{
+  isShowloadding.value = true;
+  let salesArr=[]
+    if(sales.value.length){
+        salesArr=sales.value.map(item=>{
+            return item[item.length-1]
+        })
+    }
+  const res = await customInterence.getSalesData({
+      KeyWord:search_txt.value,
+      AdminIds:salesArr.join(','),
+      CurrentIndex:page_no.value,
+      PageSize:pageSize.value
+  })
+  if(res.Ret===200){
+      const {List,Paging} = res.Data
+      tableData.value = List
+      page_no.value = Paging.CurrentIndex
+      total.value = Paging.Totals
+      pageSize.value = Paging.PageSize
+  }
+  isShowloadding.value = false;
+}
+const getSale=()=>{
+  customInterence.getSales().then((res) => {
+    if (res.Ret === 200) {
+      salesArr.value = res.Data.List;
+    }
+  });
+}
+/* 选择销售时 */
+const changeSales=()=>{
+  search_txt.value=''
+  page_no.value = 1;
+  getTableData();
+}
+const searchHandle=()=>{
+    sales.value=''
+    page_no.value = 1;
+    getTableData();
+}
+const handleChangeAuth=(item)=>{
+  customInterence.changeSaleAuth({
+    AdminId:item.AdminId,
+    Enabled:item.Enabled===0?1:0
+  }).then(res=>{
+    if(res.Ret===200){
+      ElMessage.success('操作成功')
+      getTableData()
+    }
+  })
+}
+const handleCurrentChange=(page)=>{
+    page_no.value = page
+    getTableData()
+}
+
+getTableData();
+getSale();
+
+</script>
+
+<template>
+  <div class="saleauth-wrapper">
+    <div class="search-cont">
+      <el-cascader
+        v-model="sales"
+        placeholder="请选择销售"
+        style="width: 220px"
+        :options="salesArr"
+        :props="defaultSalesProps"
+        :show-all-levels="false"
+        key="modifySales"
+        collapse-tags
+        clearable
+        filterable
+        @change="changeSales"
+      >
+      </el-cascader>
+      <el-input
+        placeholder="销售名称搜索"
+        v-model="search_txt"
+        style="max-width: 320px"
+        @input="searchHandle"
+        clearable
+      >
+        <i slot="prefix" class="el-input__icon el-icon-search"></i>
+      </el-input>
+    </div>
+    <div class="table-wrap">
+      <el-table
+        :data="tableData"
+        border
+        class="table-cont"
+        v-loading="isShowloadding"
+      >
+        <el-table-column
+          v-for="item in tableColumns"
+          :key="item.label"
+          :label="item.label"
+          :prop="item.key"
+          :min-width="item.minWidth"
+          align="center"
+        >
+            <template #default="{row}">
+                <span v-if="item.key==='Enabled'">
+                    {{row[item.key]===0?'已禁用':'已启用'}}
+                </span>
+                <span  v-else>{{ row[item.key]}}</span>
+            </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center">
+          <template #header>
+            <span>操作</span>
+            <el-tooltip
+              effect="dark"
+              placement="top-start"
+              content="该操作会禁用/启用该用户的添加客户权限并对用户发送消息"
+            >
+              <el-icon :size="14" style="vertical-align: text-top;margin-left: 3px;"><QuestionFilled /></el-icon>
+            </el-tooltip>
+          </template>
+          <template #default="{row}">
+            <span
+              @click="handleChangeAuth(row)"
+              style="cursor: pointer"
+              :style="{ color: row.Enabled===0 ? '#1DD441' : '#D1433A' }"
+              >{{ row.Enabled===0 ? "启用" : "禁用" }}</span
+            >
+          </template>
+        </el-table-column>
+        <template #empty>
+          <div style="line-height: 44px; margin: 60px 0; color: #999">
+            <img
+              src="~@/assets/img/cus_m/nodata.png"
+              alt=""
+              style="display: block; width: 160px; height: 128px; margin: auto"
+            />
+            <span>暂无数据</span>
+          </div>
+        </template>
+      </el-table>
+    </div>
+    <el-pagination
+      layout="total,prev,pager,next,jumper"
+      background
+      :current-page="page_no"
+      @current-change="handleCurrentChange"
+      :page-size="pageSize"
+      :total="total"
+      style="float: right; margin-top: 20px"
+    >
+    </el-pagination>
+  </div>
+</template>
+
+<style lang="scss">
+.saleauth-wrapper {
+  .el-cascader__search-input {
+    min-width: 30px;
+  }
+}
+</style>
+<style scoped lang="scss">
+.saleauth-wrapper {
+  height: calc(100vh - 120px);
+  background-color: #fff;
+  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
+  border-radius: 4px;
+  padding: 30px 20px;
+  box-sizing: border-box;
+
+  .frequency-cont {
+    display: flex;
+    align-items: center;
+    margin-bottom: 30px;
+
+    .frequency-ul {
+      display: flex;
+      align-items: center;
+
+      li {
+        width: 110px;
+        height: 40px;
+        text-align: center;
+        line-height: 40px;
+        border: 1px solid #b3d8ff;
+        background: #ecf5ff;
+        color: #409eff;
+        border-radius: 4px;
+        cursor: pointer;
+        margin-right: 20px;
+
+        &.act {
+          background: #409eff;
+          color: #fff;
+        }
+      }
+    }
+  }
+
+  .search-cont {
+    display: flex;
+    justify-content: space-between;
+  }
+
+  .table-wrap {
+    margin-top: 20px;
+  }
+}
+</style>

+ 200 - 0
src/views/dataReport_manage/statistic/abnormalRenewal.vue

@@ -0,0 +1,200 @@
+<script setup>
+import {ref,computed} from "vue"
+import { useRouter} from 'vue-router';
+import DatePicker from 'vue-datepicker-next';
+import { InfoFilled } from '@element-plus/icons-vue'
+
+import { dataMainInterface } from '@/api/api.js';
+import {createdHook,dataHook,computedHook,functionHook} from './hook'
+import abnormalRenewalChart from '../components/abnormalRenewalChart.vue';
+
+const $router = useRouter()
+const {dataLoading,default_tab,select_date,tableTheadColumns,staticTabs,actFilterDay,filterDaysOptions}=dataHook()
+const {activeTab}=computedHook()
+const {dateChange,changeTabHandle}=functionHook()
+
+const sellerList=ref([])
+const summaryList=ref([])
+const showChart=ref(false)
+
+const tableThead=computed(()=>{
+    if(['周度统计表','月度统计表'].includes(default_tab.value)){
+        return tableTheadColumns.value
+    }
+    return ['续约异常']
+})
+
+ 
+const getTableData=()=>{
+    dataLoading.value=true
+    sellerList.value=[]
+    summaryList.value=[]
+    dataMainInterface.unusualRenewalCustomStatistic({
+        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] : '',
+        Source: actFilterDay.value
+    }).then(res=>{
+        const { Data,Ret } = res;
+        if(Ret !== 200) return
+        sellerList.value=Data.List||[]
+        summaryList.value=Data.SummaryList||[]
+    })
+}
+
+/* 进入列表 */
+const goList=({UnusualRenewNum,UnusualRenewIds},index,parent)=>{
+    // if(!value) return
+    let column_title = getColumnTitle(index);
+    let filterDay = filterDaysOptions.find(_=>_.value===actFilterDay.value) ? `${filterDaysOptions.find(_=>_.value===actFilterDay.value).label}/` : ''
+    let title=encodeURIComponent(`${filterDay}${column_title}/${parent.SellerName}`);
+            
+    sessionStorage.setItem('renewalTab',activeTab.value.tabName)
+    const{href}=$router.resolve({
+        path: '/abnormalRenewalCustomlist',
+        query: {
+            ids: encodeURIComponent(UnusualRenewIds),
+            title
+        }
+    })
+    window.open(href,'_blank')
+}
+
+/* 获取数据对应表头 */
+const getColumnTitle=(index)=>{
+    let title = '';
+
+    if(['周度统计表','月度统计表'].includes(default_tab.value)) {
+        title=tableTheadColumns.value[index] 
+    } else {
+        title = default_tab.value || `${select_date.value[0]}~${select_date.value[1]}`;
+    }
+    
+    return title
+}
+
+getTableData()
+createdHook()
+</script>
+
+<template>
+    <div class="statistic-container" ref="reference">
+        <div style="margin-bottom:20px;">
+
+            <el-radio-group v-model="actFilterDay" @change="val => { actFilterDay=val;getTableData()}">
+                <el-radio-button 
+                    :label="item.value" 
+                    v-for="item in filterDaysOptions" 
+                    :key="item.value"
+                >{{item.label}}</el-radio-button>
+            </el-radio-group>
+        </div>
+
+        <div class="frequency-cont" style="position: relative;">
+            <el-tabs v-model="default_tab" @tab-click="item =>{changeTabHandle(item.paneName,getTableData)}" style="margin-right:20px">
+                <!--  -->
+                <el-tab-pane 
+                    v-for="tab in staticTabs" 
+                    :key="tab" 
+                    :label="tab" 
+                    :name="tab"
+                />
+            </el-tabs>
+			<date-picker
+                v-model:value="select_date"
+                type="date" 
+                range
+                value-type="format"
+                :clearable="false"
+                @change="dateChange(getTableData)"
+                placeholder="请选择统计时间"
+            />
+            <span style="color:#A3A3A3;display:inline-block;margin-left:20px">续约异常:{{filterDaysOptions.find(_=>_.value===actFilterDay).msg}}</span>
+
+            <div style="color:#409EFF;position: absolute;top:10px;right:10px;cursor: pointer;" @click="showChart=true" v-if="actFilterDay===1">
+                <img src="~@/assets/img/icons/changeLang.png" alt="">
+                <span style="display:inline-block;position: relative;top:-3px;left:3px">统计图</span>
+            </div>
+        </div>
+        <div class="table-cont" v-show="dataLoading">
+            <div class="table-body-wrapper">
+                <table>
+                    <thead>
+						<tr>
+							<td class="thead-rs">销售</td>
+                            <td 
+                                v-for="item in tableThead"
+								:key="item" 
+								class="head-column"
+                            >{{item}}</td>
+						</tr>
+					</thead>
+                    <tbody>
+                        <tr v-for="rs in sellerList" :key="rs.SellerId">
+                            <td class="thead-rs">{{rs.SellerName}}</td>
+                            <td 
+								:class="['data-cell',{link: data.UnusualRenewNum}]" 
+								v-for="data,index in rs.CompanyRenewRecordNumList" 
+								:key="data.UnusualRenewIds"
+							>		
+								<span 
+									@click="goList(data,index,rs)"
+								>
+									{{ data.UnusualRenewNum !== 0 ? data.UnusualRenewNum : '' }}
+								</span>
+							</td>
+                        </tr>
+                    </tbody>
+                    <tfoot>
+                        <tr>
+                            <td>合计</td>
+                            <td 
+                                :class="['data-cell',{link: item.UnusualRenewNum}]" 
+                                v-for="item,index in summaryList" 
+                                :key="item.UnusualRenewIds"
+                            >
+                                <span
+                                    @click="goList(item,index,{SellerName:'合计'})"
+                                >
+                                    {{item.UnusualRenewNum||''}}
+                                </span>
+                            </td>
+                        </tr>
+                        <tr v-if="actFilterDay===1">
+                            <td>
+                                <span>异常率</span>
+                                <el-tooltip 
+									effect="dark" 
+									placement="top-start"
+									content="异常率=当期续约异常客户总数/截止当期系统中存量客户总数"
+								>
+									<el-icon :size="14" style="vertical-align: text-top;margin-left: 3px"><InfoFilled /></el-icon>
+								</el-tooltip>
+                            </td>
+                            <td v-for="item in summaryList" :key="item.UnusualRenewIds">{{item.UnusualRate||''}}</td>
+                        </tr>
+                    </tfoot>
+                </table>
+            </div>
+        </div>
+        <abnormalRenewalChart v-if="showChart" @close="showChart=false"/>
+    </div>
+</template>
+
+<style lang="scss" scoped>
+@import './index.scss';
+.statistic-container{
+    height: calc(100vh - 180px);
+    position: relative;
+}
+</style>
+<style lang="scss">
+.statistic-container{
+    .el-tabs__header {
+        margin-bottom: 0 !important;
+    }
+    .el-tabs__nav-wrap::after {
+        background: transparent;
+    }
+}    
+</style>

+ 459 - 0
src/views/dataReport_manage/statistic/contractCustom.vue

@@ -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>

+ 13 - 15
src/views/dataReport_manage/statistic/hook.js

@@ -30,6 +30,16 @@ const tableTheadColumns=ref([
 	`上四周(${getWeekOrMonthDate(4)})`,
 	`上五周(${getWeekOrMonthDate(5)})`])//动态表头配置
 const staticTabs=ref([ '周度统计表','月度统计表','近1个月','近3个月','近6个月' ])
+const actFilterDay=ref(1)
+const filterDaysOptions=[
+	{ label:'+60D',value: 1,msg:'合同到期后两个月内未签约' },
+	{ label:'+30D',value: 4,msg:'合同到期后一个月内未签约' },
+	{ label:'到期',value: 5,msg:'合同到期未签约' },
+	{ label:'-30D',value: 6,msg:'合同到期前一个月' },
+	{ label:'-60D',value: 7,msg:'合同到期前两个月' },
+	{ label:'-90D',value: 8,msg:'合同到期前三个月' },
+	{ label:'-120D',value: 9,msg:'合同到期前四个月' },
+]
 
 const Role=computed(()=>{
 	return localStorage.getItem('Role');
@@ -235,7 +245,9 @@ export function dataHook(){
 		totalGroupArr,
 		datalist,
 		tableTheadColumns,
-		staticTabs
+		staticTabs,
+		actFilterDay,
+		filterDaysOptions
 	}
 }
 export function computedHook(){
@@ -254,18 +266,4 @@ export function functionHook(){
 	}
 }
 
-	// data() {
-	// 	return {
-	// 		filterDaysOptions: [
-	// 			{ label:'+60D',value: 1,msg:'合同到期后两个月内未签约' },
-	// 			{ label:'+30D',value: 4,msg:'合同到期后一个月内未签约' },
-	// 			{ label:'到期',value: 5,msg:'合同到期未签约' },
-	// 			{ label:'-30D',value: 6,msg:'合同到期前一个月' },
-	// 			{ label:'-60D',value: 7,msg:'合同到期前两个月' },
-	// 			{ label:'-90D',value: 8,msg:'合同到期前三个月' },
-	// 			{ label:'-120D',value: 9,msg:'合同到期前四个月' },
-	// 		],
-	// 		actFilterDay: 1
-	// 	}
-	// },
 

+ 6 - 4
src/views/dataReport_manage/statistic/newCustomlist.vue

@@ -316,10 +316,12 @@ init()
 					<el-button link type="primary" @click="handleShowShareRecode(scope.row,'list')" style="padding:12px 0;">沟通记录</el-button>
 				</template>
 			</el-table-column>
-			<div slot="empty" style="line-height:44px;margin:60px 0;color:#999;">
-				<img src="~@/assets/img/cus_m/nodata.png" alt="" style="display:block;width:160px;height:128px;margin: auto;">
-				<span>暂无数据</span>
-			</div>
+			<template #empty>
+				<div style="line-height: 44px; margin: 60px 0; color: #999">
+					<img src="~@/assets/img/cus_m/nodata.png" alt="" style="display: block; width: 160px; height: 128px; margin: auto"/>
+					<span>暂无数据</span>
+				</div>
+			</template>
 		</el-table>
 		<div class="bottom">
 			<m-page

+ 242 - 0
src/views/dataReport_manage/statistic/stockCustom.vue

@@ -0,0 +1,242 @@
+<script setup>
+import { ref,computed } from "vue";
+import _ from 'lodash'
+import { InfoFilled,ArrowUp,ArrowDown } from '@element-plus/icons-vue'
+import moment from "moment"
+import $ from "jquery"
+import DatePicker from "vue-datepicker-next"
+
+import { dataMainInterface } from '@/api/api.js';
+
+const dataLoading=ref(false)
+const select_date=ref(moment().format('YYYY-MM-DD'))
+const datalist=ref([])
+const tableTheadColumns=['试用','推进','跟踪','预备','未分类','活跃','正式']
+const tipMap=new Map([
+	['试用1','截止到查询日期,试用状态的客户数量'],
+	['推进1','截止到查询日期,试用(推进)状态的客户数量'],
+	['跟踪1','截止到查询日期,试用(跟踪)状态的客户数量'],
+	['预备1','截止到查询日期,试用(预备)状态的客户数量'],
+	['未分类1','截止到查询日期,试用(未分类)状态的客户数量'],
+	['活跃1','截止到查询日期,上述试用状态的客户中,累计报告阅读次数≥50次的客户'],
+	['正式1','截止到查询日期,正式状态的客户数量'],
+
+	['试用2','截止到查询日期,试用状态的客户数量'],
+	['推进2','截止到查询日期,试用(推进)状态的客户数量'],
+	['跟踪2','截止到查询日期,试用(跟踪)状态的客户数量'],
+	['预备2','截止到查询日期,试用(预备)状态的客户数量'],
+	['未分类2','截止到查询日期,试用(未分类)状态的客户数量'],
+	['活跃2','截止到某一日期,累计互动量≥50次的试用客户'],
+	['正式2','截止到查询日期,正式状态的客户数量'],
+])
+const totalGroupArr=ref([])
+
+const Role = computed(()=>{
+	return localStorage.getItem('Role');
+})
+const activeTab = computed(()=>{
+	let tabName = sessionStorage.getItem('renewalTab')?sessionStorage.getItem('renewalTab'):'FICC'
+	return {
+		tabName, // FICC QY
+		tabSummationName:tabName == 'FICC'?'ficc总合计':'权益总合计',
+		productionId:tabName == 'FICC'?1:2, // 1 FICC 2 权益
+	}
+})
+
+// 切换 FICC 和 权益 TAB
+const switchTab=(tabName)=>{
+		activeTab.value.tabName = tabName
+		activeTab.value.tabSummationName = tabName == 'FICC'?"ficc总合计":"权益总合计"
+		activeTab.value.productionId = tabName == 'FICC'?1:2
+		getTableData()
+}
+
+/* 获取表格数据 */
+const getTableData=()=>{
+	dataLoading.value = false;
+	dataMainInterface.stockcustomStatistic({
+		Date: select_date.value,
+		ProductId:activeTab.value.productionId
+	}).then(res => {
+		const { Data,Ret } = res;
+		if(Ret !== 200) return
+
+		//总合计数据处理
+		totalGroupArr.value = filterTableData(Data.CompanyReportRecordNumList);
+
+		//处理数据结构
+		let data = _.cloneDeep(Data.List);
+		if(!['admin','ficc_admin'].includes(Role.value)) data = data.sort((a,b) => b.Item.length - a.Item.length);
+
+		data.forEach(item => {
+			item.showDetail=false
+			let groupDataArr = filterTableData(item.CompanyReportRecordNumList);
+			item.subGroupArr = groupDataArr
+
+			item.Item && item.Item.forEach(sub_item => {
+				
+				let dataArr = filterTableData(sub_item.CompanyReportRecordNumList,sub_item.AdminId)
+				sub_item.dataArr = dataArr
+			})
+		})
+
+		datalist.value = data;
+		dataLoading.value = true;
+		
+	})
+}
+
+const dateChangeHandle=()=>{
+	$('.table-body-wrapper')[0].scrollTop = 0; 
+	getTableData();
+}
+
+/* 处理数据结构 便于页面渲染 */
+const filterTableData=(data)=>{
+	let list = data.map(item => ([
+		{
+			key: '试用',
+			value: item.TryOutNum,
+		},
+		{
+			key: '推进',
+			value: item.TryStagePushNum,
+		},
+		{
+			key: '跟踪',
+			value: item.TryStageFollowNum,
+		},
+		{
+			key: '预备',
+			value: item.TryStageReadyNum,
+		},
+		{
+			key: '未分类',
+			value: item.TryStageInitNum,
+		},
+		{
+			key: '活跃',
+			value: item.ActiveNum,
+		},
+		{
+			key: '正式',
+			value: item.FormalNum,
+		}
+	]))
+	
+	return list.flat(Infinity);
+}
+
+// start
+if(Role.value.indexOf('rai')!=-1){
+	activeTab.value.tabName = 'QY'
+	activeTab.value.tabSummationName = '权益总合计'
+	activeTab.value.productionId = 2
+}
+getTableData();
+
+</script>
+
+<template>
+	<div class="statistic-container">
+		<div class="custom-tab-box" v-if="Role==='admin'">
+			<div class="custom-tab" :class="activeTab.tabName =='FICC' && 'activeTab'" @click="switchTab('FICC')">
+				FICC
+			</div>
+			<div class="custom-tab" :class="activeTab.tabName =='QY' && 'activeTab'" @click="switchTab('QY')">
+				权益
+			</div>
+		</div>
+		<div class="frequency-cont">
+			<date-picker
+			v-model:value="select_date"
+			type="date" 
+			value-type="format"
+			:clearable="false"
+			@change="dateChangeHandle"
+			placeholder="请选择统计时间"/>
+		</div>
+		<div class="table-cont" v-show="dataLoading">
+			<div class="table-body-wrapper">
+				<table>
+					<thead>
+						<tr>
+							<td rowspan="2" class="thead-rs">组别</td>
+							<td rowspan="2" class="thead-rs">销售</td>
+							<td
+								v-for="item in tableTheadColumns" 
+								:key="item" 
+								class="head-column"
+							>
+								{{item}}
+								<el-tooltip 
+									effect="dark" 
+									placement="top-start"
+									:content="tipMap.get(item+activeTab.productionId)"
+								>
+									<el-icon :size="14" style="vertical-align: text-top;"><InfoFilled /></el-icon>
+								</el-tooltip>
+							</td> 
+						</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">
+									{{ group_data.value !== 0 ? group_data.value : '' }}
+								</td>
+							</tr>
+							<template v-if="item.Item.length">
+								<tr :style="{display:item.showDetail?'table-row':'none'}">
+									<td :rowspan="item.Item.length+1" class="thead-rs">{{item.Name}}</td>
+								</tr>
+
+								<tr v-for="rs in item.Item" :key="rs.AdminId" :style="{display:item.showDetail?'table-row':'none'}">
+									<td class="thead-rs">{{rs.Name}}</td>
+
+									<td class="data-cell" v-for="(data,data_key) in rs.dataArr" :key="data_key">
+										{{ data.value !== 0 ? data.value : '' }}
+									</td>
+									
+								</tr>
+							</template>
+							
+							
+					</tbody>
+
+					<tfoot>
+						<tr>
+							<td colspan="2">{{activeTab.tabSummationName}}</td>
+							<td v-for="(total_data,total_data_key) in totalGroupArr" :key="total_data_key">
+								{{ total_data.value !== 0 ? total_data.value : '' }}
+							</td>
+						</tr>
+					</tfoot>
+				</table>
+			</div>	
+		</div>
+
+	</div>
+</template>
+
+<style lang='scss' scoped>
+*{ box-sizing: border-box;}
+@import './index.scss';
+/* .thead-rs {
+	width: 120px !important;
+}
+.head-column {
+	width: 10% !important;
+}
+.data-cell{
+	width: 10% !important;
+} */
+</style>