【招生用户端】 新增# 工作台:对接成交用户统计接口
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