【招生用户端】 新增# 工作台:对接成交用户统计接口
							parent
							
								
									c57cc282fb
								
							
						
					
					
						commit
						5110a2c267
					
				|  | @ -12,15 +12,15 @@ export function convertProcessApi(params?: any) { | |||
| export function clueStatusApi(params?: any) { | ||||
|     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) { | ||||
|     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 { useCreateModal } from './useCreateModal' | ||||
| import { toast, formatFileSize } from '@/utils/util' | ||||
| import { postLists } from '@/api/account_center/postion' | ||||
| 
 | ||||
| export interface CategoryProp { | ||||
|     id: number | ||||
|  | @ -311,3 +312,21 @@ export function useUploadMoreAction() { | |||
|         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> | ||||
|     <div class="flex-1 w-full chart-card"> | ||||
|         <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> | ||||
|     </div> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { completedCustomerListApi } from '@/api/workbench' | ||||
| import card from './card.vue' | ||||
| 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) { | ||||
|     return { | ||||
|         name, | ||||
|  | @ -20,9 +18,11 @@ function createBarSeries(data, name, 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, '客户数', 'clueNumber'), createBarSeries(data, '成交客户数', 'client')] | ||||
| const series = [createBarSeries(data.value, '客户数', 'clientCount'), createBarSeries(data.value, '成交客户数', 'transactionClient')] | ||||
| 
 | ||||
| const option = ref({ | ||||
|     color: ['#0E66FB', '#96B2D9'], | ||||
|  | @ -40,7 +40,7 @@ const option = ref({ | |||
|     xAxis: [ | ||||
|         { | ||||
|             type: 'category', | ||||
|             data: xAxisData() | ||||
|             data: xAxisData.value | ||||
|         } | ||||
|     ], | ||||
|     yAxis: [ | ||||
|  | @ -53,7 +53,54 @@ const option = ref({ | |||
|     ], | ||||
|     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> | ||||
| 
 | ||||
| <style scoped lang="scss"> | ||||
| @media (max-width: 1000px) { | ||||
|     .chart-card { | ||||
|  |  | |||
|  | @ -3,45 +3,70 @@ | |||
|         <card title="TOP5"> | ||||
|             <template #right> | ||||
|                 <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 }} | ||||
|                     </span> | ||||
|                 </div> | ||||
|             </template> | ||||
|             <el-table :data="tableData"> | ||||
|                 <el-table-column prop="index" label="排名" width="70" /> | ||||
|                 <el-table-column prop="name" label="负责人" width="180" /> | ||||
|                 <el-table-column prop="totalNumber" label="总数" /> | ||||
|             </el-table> | ||||
|             <template v-if="tableData.length > 0"> | ||||
|                 <el-table :data="tableData" v-loading="loading"> | ||||
|                     <el-table-column prop="rank" label="排名" width="70" /> | ||||
|                     <el-table-column prop="username" label="负责人" width="180" /> | ||||
|                     <el-table-column prop="clueCount" label="总数" /> | ||||
|                 </el-table> | ||||
|             </template> | ||||
|             <template v-else> | ||||
|                 <el-empty description="暂无数据" /> | ||||
|             </template> | ||||
|         </card> | ||||
|     </div> | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { rankListApi } from '@/api/workbench' | ||||
| import card from './card.vue' | ||||
| const positions = ref([ | ||||
|     { name: '电销', id: 5 }, | ||||
|     { name: '招生', id: 6 } | ||||
| ]) | ||||
| const postId = ref(5) | ||||
| import type { IForm } from '../index.vue' | ||||
| import { usePositionData } from '@/hooks/useCommon' | ||||
| 
 | ||||
| const tableData = ref([ | ||||
|     { | ||||
|         index: 1, | ||||
|         name: 'John Brown', | ||||
|         totalNumber: 32 | ||||
|     }, | ||||
|     { | ||||
|         index: 2, | ||||
|         name: 'John Brown', | ||||
|         totalNumber: 32 | ||||
|     }, | ||||
|     { | ||||
|         index: 3, | ||||
|         name: 'John Brown', | ||||
|         totalNumber: 32 | ||||
| const { positionOptions, postId, fetchPostionData } = usePositionData() | ||||
| 
 | ||||
| const emit = defineEmits(['refresh']) | ||||
| 
 | ||||
| const tableData = ref([]) | ||||
| const loading = ref(false) | ||||
| const fetchData = async (payload: IForm) => { | ||||
|     if (!positionOptions.value.length) await fetchPostionData() | ||||
|     if (tableData.value.length > 0) tableData.value = [] | ||||
|     loading.value = true | ||||
|     try { | ||||
|         const newPayload = { | ||||
|             ...payload, | ||||
|             post: postId.value | ||||
|         } | ||||
|         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> | ||||
| <style scoped lang="scss"> | ||||
| .rank { | ||||
|  |  | |||
|  | @ -4,10 +4,10 @@ | |||
|         <data-overview ref="dataOverviewRef" /> | ||||
|         <div class="flex gap-[16px] flex-wrap"> | ||||
|             <conversion-process-chart ref="coversionProcessChartRef" /> | ||||
|             <converted-chart /> | ||||
|             <converted-chart ref="convertedChartRef" /> | ||||
|         </div> | ||||
|         <div class="flex gap-[16px] flex-wrap"> | ||||
|             <rank /> | ||||
|             <rank ref="rankRef" @refresh="refreshData" /> | ||||
|             <clue-status-pie ref="clueStatusPieRef" /> | ||||
|             <!-- <converted-line-chart /> --> | ||||
|         </div> | ||||
|  | @ -37,6 +37,8 @@ const form = ref<IForm>({ | |||
|     createTimeEnd: getCurDate('end'), | ||||
|     userId: '' | ||||
| }) | ||||
| const convertedChartRef = ref<InstanceType<typeof convertedChart>>() | ||||
| const rankRef = ref<InstanceType<typeof rank>>() | ||||
| const clueStatusPieRef = ref<InstanceType<typeof clueStatusPie>>() | ||||
| const coversionProcessChartRef = ref<InstanceType<typeof conversionProcessChart>>() | ||||
| const dataOverviewRef = ref<InstanceType<typeof dataOverview>>() | ||||
|  | @ -57,6 +59,11 @@ const fetchAllData = (defaultValue?: number) => { | |||
|     dataOverviewRef.value?.fetchData(form.value) | ||||
|     coversionProcessChartRef.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> | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue