【招生用户端】 新增# 工作台:对接成交用户统计接口
							parent
							
								
									c57cc282fb
								
							
						
					
					
						commit
						5110a2c267
					
				|  | @ -12,15 +12,15 @@ export function convertProcessApi(params?: any) { | ||||||
| export function clueStatusApi(params?: any) { | export function clueStatusApi(params?: any) { | ||||||
|     return request.get({ url: '/control/clueStatistics', params }) |     return request.get({ url: '/control/clueStatistics', params }) | ||||||
| } | } | ||||||
|  | // Top5
 | ||||||
|  | export function rankListApi(params?: any) { | ||||||
|  |     return request.get({ url: '/control/top', params }) | ||||||
|  | } | ||||||
|  | // 成交客户统计
 | ||||||
|  | export function completedCustomerListApi(params?: any) { | ||||||
|  |     return request.get({ url: '/control/transactionCustomerStatistics', params }) | ||||||
|  | } | ||||||
| // 获取所有组织以及人员信息
 | // 获取所有组织以及人员信息
 | ||||||
| export function allUserListApi(params?: any) { | export function allUserListApi(params?: any) { | ||||||
|     return request.get({ url: '/organization/getAllChildOrgInfo', params }) |     return request.get({ url: '/organization/getAllChildOrgInfo', params }) | ||||||
| } | } | ||||||
| // 获取所有团队
 |  | ||||||
| export function allTeamListApi(params?: any) { |  | ||||||
|     return request.get({ url: '/organization/getAllGroup', params }) |  | ||||||
| } |  | ||||||
| // 获取所有组织
 |  | ||||||
| export function allOrgListApi(params?: any) { |  | ||||||
|     return request.get({ url: '/organization/getAllOrg', params }) |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ import { apiFeedbackAgreement, apiMasterWorkerApplyAgreement, apiMasterWorkerPhy | ||||||
| import { applyForEdit } from '@/api/finance/withdraw' | import { applyForEdit } from '@/api/finance/withdraw' | ||||||
| import { useCreateModal } from './useCreateModal' | import { useCreateModal } from './useCreateModal' | ||||||
| import { toast, formatFileSize } from '@/utils/util' | import { toast, formatFileSize } from '@/utils/util' | ||||||
|  | import { postLists } from '@/api/account_center/postion' | ||||||
| 
 | 
 | ||||||
| export interface CategoryProp { | export interface CategoryProp { | ||||||
|     id: number |     id: number | ||||||
|  | @ -311,3 +312,21 @@ export function useUploadMoreAction() { | ||||||
|         previewPdf |         previewPdf | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export function usePositionData() { | ||||||
|  |     const positionOptions = ref<any[]>([]) | ||||||
|  |     const postId = ref() | ||||||
|  |     const fetchPostionData = async (callback?: (params: []) => void) => { | ||||||
|  |         try { | ||||||
|  |             const result = await postLists() | ||||||
|  |             positionOptions.value = result.lists ?? [] | ||||||
|  |             if (result.lists.length > 0) postId.value = result.lists[0].id | ||||||
|  |             callback && callback(result.lists) | ||||||
|  |         } catch (error) {} | ||||||
|  |     } | ||||||
|  |     return { | ||||||
|  |         positionOptions, | ||||||
|  |         postId, | ||||||
|  |         fetchPostionData | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1,18 +1,16 @@ | ||||||
| <template> | <template> | ||||||
|     <div class="flex-1 w-full chart-card"> |     <div class="flex-1 w-full chart-card"> | ||||||
|         <card title="成交客户统计"> |         <card title="成交客户统计"> | ||||||
|             <v-charts style="height: 350px" :autoresize="true" :option="option" /> |             <v-charts style="height: 350px" ref="chartRef" v-loading="loading" :autoresize="true" :option="option" /> | ||||||
|         </card> |         </card> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
|  | import { completedCustomerListApi } from '@/api/workbench' | ||||||
| import card from './card.vue' | import card from './card.vue' | ||||||
| import vCharts from 'vue-echarts' | import vCharts from 'vue-echarts' | ||||||
|  | import type { IForm } from '../index.vue' | ||||||
| 
 | 
 | ||||||
| const data = [ |  | ||||||
|     { name: '湛江团队', clueNumber: 52, client: 52, rate: 100 }, |  | ||||||
|     { name: '广州团队', clueNumber: 8, client: 6, rate: 15 } |  | ||||||
| ] |  | ||||||
| function createBarSeries(data, name, field) { | function createBarSeries(data, name, field) { | ||||||
|     return { |     return { | ||||||
|         name, |         name, | ||||||
|  | @ -20,9 +18,11 @@ function createBarSeries(data, name, field) { | ||||||
|         data: data.map(item => item[field]) |         data: data.map(item => item[field]) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | const chartRef = ref() | ||||||
|  | const data = ref<any[]>([]) | ||||||
|  | const xAxisData = ref([]) | ||||||
| 
 | 
 | ||||||
| const xAxisData = () => data.map(item => item.name) | const series = [createBarSeries(data.value, '客户数', 'clientCount'), createBarSeries(data.value, '成交客户数', 'transactionClient')] | ||||||
| const series = [createBarSeries(data, '客户数', 'clueNumber'), createBarSeries(data, '成交客户数', 'client')] |  | ||||||
| 
 | 
 | ||||||
| const option = ref({ | const option = ref({ | ||||||
|     color: ['#0E66FB', '#96B2D9'], |     color: ['#0E66FB', '#96B2D9'], | ||||||
|  | @ -40,7 +40,7 @@ const option = ref({ | ||||||
|     xAxis: [ |     xAxis: [ | ||||||
|         { |         { | ||||||
|             type: 'category', |             type: 'category', | ||||||
|             data: xAxisData() |             data: xAxisData.value | ||||||
|         } |         } | ||||||
|     ], |     ], | ||||||
|     yAxis: [ |     yAxis: [ | ||||||
|  | @ -53,7 +53,54 @@ const option = ref({ | ||||||
|     ], |     ], | ||||||
|     series |     series | ||||||
| }) | }) | ||||||
|  | const loading = ref(false) | ||||||
|  | 
 | ||||||
|  | const fetchData = async (payload: IForm) => { | ||||||
|  |     loading.value = true | ||||||
|  |     try { | ||||||
|  |         const result = await completedCustomerListApi(payload) | ||||||
|  |         data.value = result.map((item: any) => { | ||||||
|  |             const { clientCount, transactionClient } = item.leadToCustomerStatisticsVo | ||||||
|  |             return { | ||||||
|  |                 name: item.organizationName, | ||||||
|  |                 clientCount, | ||||||
|  |                 transactionClient | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |         xAxisData.value = result.map((item: any) => item.organizationName) | ||||||
|  |         const allZero = data.value.every(item => item.clientCount == 0 && item.transactionClient == 0) | ||||||
|  |         if (allZero) { | ||||||
|  |             chartRef.value.setOption({ | ||||||
|  |                 title: { | ||||||
|  |                     text: '暂无数据', | ||||||
|  |                     x: 'center', | ||||||
|  |                     y: 'center' | ||||||
|  |                 }, | ||||||
|  |                 xAxis: [ | ||||||
|  |                     { | ||||||
|  |                         type: 'category', | ||||||
|  |                         data: [], | ||||||
|  |                         splitLine: { | ||||||
|  |                             show: false | ||||||
|  |                         }, | ||||||
|  |                         axisLine: { | ||||||
|  |                             show: false | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 ], | ||||||
|  |                 legend: { | ||||||
|  |                     show: false | ||||||
|  |                 } | ||||||
|  |             }) | ||||||
|  |         } | ||||||
|  |     } catch (error) {} | ||||||
|  |     loading.value = false | ||||||
|  | } | ||||||
|  | defineExpose({ | ||||||
|  |     fetchData | ||||||
|  | }) | ||||||
| </script> | </script> | ||||||
|  | 
 | ||||||
| <style scoped lang="scss"> | <style scoped lang="scss"> | ||||||
| @media (max-width: 1000px) { | @media (max-width: 1000px) { | ||||||
|     .chart-card { |     .chart-card { | ||||||
|  |  | ||||||
|  | @ -3,45 +3,70 @@ | ||||||
|         <card title="TOP5"> |         <card title="TOP5"> | ||||||
|             <template #right> |             <template #right> | ||||||
|                 <div class="positions"> |                 <div class="positions"> | ||||||
|                     <span class="default" :class="{ active: item.id == postId }" v-for="item in positions" :key="item.id" @click="postId = item.id"> |                     <span | ||||||
|  |                         class="default" | ||||||
|  |                         :class="{ active: item.id == postId }" | ||||||
|  |                         v-for="item in positionOptions" | ||||||
|  |                         :key="item.id" | ||||||
|  |                         @click="postId = item.id" | ||||||
|  |                     > | ||||||
|                         {{ item.name }} |                         {{ item.name }} | ||||||
|                     </span> |                     </span> | ||||||
|                 </div> |                 </div> | ||||||
|             </template> |             </template> | ||||||
|             <el-table :data="tableData"> |             <template v-if="tableData.length > 0"> | ||||||
|                 <el-table-column prop="index" label="排名" width="70" /> |                 <el-table :data="tableData" v-loading="loading"> | ||||||
|                 <el-table-column prop="name" label="负责人" width="180" /> |                     <el-table-column prop="rank" label="排名" width="70" /> | ||||||
|                 <el-table-column prop="totalNumber" label="总数" /> |                     <el-table-column prop="username" label="负责人" width="180" /> | ||||||
|  |                     <el-table-column prop="clueCount" label="总数" /> | ||||||
|                 </el-table> |                 </el-table> | ||||||
|  |             </template> | ||||||
|  |             <template v-else> | ||||||
|  |                 <el-empty description="暂无数据" /> | ||||||
|  |             </template> | ||||||
|         </card> |         </card> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||||
|  | import { rankListApi } from '@/api/workbench' | ||||||
| import card from './card.vue' | import card from './card.vue' | ||||||
| const positions = ref([ | import type { IForm } from '../index.vue' | ||||||
|     { name: '电销', id: 5 }, | import { usePositionData } from '@/hooks/useCommon' | ||||||
|     { name: '招生', id: 6 } |  | ||||||
| ]) |  | ||||||
| const postId = ref(5) |  | ||||||
| 
 | 
 | ||||||
| const tableData = ref([ | const { positionOptions, postId, fetchPostionData } = usePositionData() | ||||||
|     { | 
 | ||||||
|         index: 1, | const emit = defineEmits(['refresh']) | ||||||
|         name: 'John Brown', | 
 | ||||||
|         totalNumber: 32 | const tableData = ref([]) | ||||||
|     }, | const loading = ref(false) | ||||||
|     { | const fetchData = async (payload: IForm) => { | ||||||
|         index: 2, |     if (!positionOptions.value.length) await fetchPostionData() | ||||||
|         name: 'John Brown', |     if (tableData.value.length > 0) tableData.value = [] | ||||||
|         totalNumber: 32 |     loading.value = true | ||||||
|     }, |     try { | ||||||
|     { |         const newPayload = { | ||||||
|         index: 3, |             ...payload, | ||||||
|         name: 'John Brown', |             post: postId.value | ||||||
|         totalNumber: 32 |  | ||||||
|         } |         } | ||||||
| ]) |         const result = await rankListApi(newPayload) | ||||||
|  |         console.log(result) | ||||||
|  | 
 | ||||||
|  |         tableData.value = result ?? [] | ||||||
|  |     } catch (error) {} | ||||||
|  |     loading.value = false | ||||||
|  | } | ||||||
|  | watch( | ||||||
|  |     () => postId.value, | ||||||
|  |     (newVal, oldVal) => { | ||||||
|  |         if (newVal !== oldVal) { | ||||||
|  |             emit('refresh') | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | ) | ||||||
|  | defineExpose({ | ||||||
|  |     fetchData | ||||||
|  | }) | ||||||
| </script> | </script> | ||||||
| <style scoped lang="scss"> | <style scoped lang="scss"> | ||||||
| .rank { | .rank { | ||||||
|  |  | ||||||
|  | @ -4,10 +4,10 @@ | ||||||
|         <data-overview ref="dataOverviewRef" /> |         <data-overview ref="dataOverviewRef" /> | ||||||
|         <div class="flex gap-[16px] flex-wrap"> |         <div class="flex gap-[16px] flex-wrap"> | ||||||
|             <conversion-process-chart ref="coversionProcessChartRef" /> |             <conversion-process-chart ref="coversionProcessChartRef" /> | ||||||
|             <converted-chart /> |             <converted-chart ref="convertedChartRef" /> | ||||||
|         </div> |         </div> | ||||||
|         <div class="flex gap-[16px] flex-wrap"> |         <div class="flex gap-[16px] flex-wrap"> | ||||||
|             <rank /> |             <rank ref="rankRef" @refresh="refreshData" /> | ||||||
|             <clue-status-pie ref="clueStatusPieRef" /> |             <clue-status-pie ref="clueStatusPieRef" /> | ||||||
|             <!-- <converted-line-chart /> --> |             <!-- <converted-line-chart /> --> | ||||||
|         </div> |         </div> | ||||||
|  | @ -37,6 +37,8 @@ const form = ref<IForm>({ | ||||||
|     createTimeEnd: getCurDate('end'), |     createTimeEnd: getCurDate('end'), | ||||||
|     userId: '' |     userId: '' | ||||||
| }) | }) | ||||||
|  | const convertedChartRef = ref<InstanceType<typeof convertedChart>>() | ||||||
|  | const rankRef = ref<InstanceType<typeof rank>>() | ||||||
| const clueStatusPieRef = ref<InstanceType<typeof clueStatusPie>>() | const clueStatusPieRef = ref<InstanceType<typeof clueStatusPie>>() | ||||||
| const coversionProcessChartRef = ref<InstanceType<typeof conversionProcessChart>>() | const coversionProcessChartRef = ref<InstanceType<typeof conversionProcessChart>>() | ||||||
| const dataOverviewRef = ref<InstanceType<typeof dataOverview>>() | const dataOverviewRef = ref<InstanceType<typeof dataOverview>>() | ||||||
|  | @ -57,6 +59,11 @@ const fetchAllData = (defaultValue?: number) => { | ||||||
|     dataOverviewRef.value?.fetchData(form.value) |     dataOverviewRef.value?.fetchData(form.value) | ||||||
|     coversionProcessChartRef.value?.fetchData(form.value) |     coversionProcessChartRef.value?.fetchData(form.value) | ||||||
|     clueStatusPieRef.value?.fetchData(form.value) |     clueStatusPieRef.value?.fetchData(form.value) | ||||||
|  |     rankRef.value?.fetchData(form.value) | ||||||
|  |     convertedChartRef.value?.fetchData(form.value) | ||||||
|  | } | ||||||
|  | const refreshData = () => { | ||||||
|  |     rankRef.value?.fetchData(form.value) | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue