|
|
@ -18,7 +18,7 @@ |
|
|
|
<CountTo |
|
|
|
<CountTo |
|
|
|
class="text-20px number-font" |
|
|
|
class="text-20px number-font" |
|
|
|
:start-val="0" |
|
|
|
:start-val="0" |
|
|
|
:end-val="10" |
|
|
|
:end-val="clueInfo.todayFollowingNum" |
|
|
|
:duration="2600" |
|
|
|
:duration="2600" |
|
|
|
/> |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
@ -28,7 +28,7 @@ |
|
|
|
<CountTo |
|
|
|
<CountTo |
|
|
|
class="text-20px number-font" |
|
|
|
class="text-20px number-font" |
|
|
|
:start-val="0" |
|
|
|
:start-val="0" |
|
|
|
:end-val="25" |
|
|
|
:end-val="clueInfo.todayFollowedNum" |
|
|
|
:duration="2600" |
|
|
|
:duration="2600" |
|
|
|
/> |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
@ -38,7 +38,7 @@ |
|
|
|
<CountTo |
|
|
|
<CountTo |
|
|
|
class="text-20px number-font" |
|
|
|
class="text-20px number-font" |
|
|
|
:start-val="0" |
|
|
|
:start-val="0" |
|
|
|
:end-val="2" |
|
|
|
:end-val="clueInfo.todaySignedNum" |
|
|
|
:duration="2600" |
|
|
|
:duration="2600" |
|
|
|
/> |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
@ -48,7 +48,7 @@ |
|
|
|
<CountTo |
|
|
|
<CountTo |
|
|
|
class="text-20px number-font" |
|
|
|
class="text-20px number-font" |
|
|
|
:start-val="0" |
|
|
|
:start-val="0" |
|
|
|
:end-val="235" |
|
|
|
:end-val="clueInfo.outFollowNum" |
|
|
|
:duration="2600" |
|
|
|
:duration="2600" |
|
|
|
/> |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
@ -58,7 +58,7 @@ |
|
|
|
<CountTo |
|
|
|
<CountTo |
|
|
|
class="text-20px number-font" |
|
|
|
class="text-20px number-font" |
|
|
|
:start-val="0" |
|
|
|
:start-val="0" |
|
|
|
:end-val="0" |
|
|
|
:end-val="clueInfo.unknownNum" |
|
|
|
:duration="2600" |
|
|
|
:duration="2600" |
|
|
|
/> |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
@ -99,9 +99,9 @@ |
|
|
|
<template #header> |
|
|
|
<template #header> |
|
|
|
<div class="flex justify-between items-center"> |
|
|
|
<div class="flex justify-between items-center"> |
|
|
|
<span>跟进榜Top10</span> |
|
|
|
<span>跟进榜Top10</span> |
|
|
|
<el-radio-group v-model="followDate" size="small"> |
|
|
|
<el-radio-group v-model="followDate" size="small" @change="getFollowList"> |
|
|
|
<el-radio label="day">本日</el-radio> |
|
|
|
<el-radio :label="1">本日</el-radio> |
|
|
|
<el-radio label="month">本月</el-radio> |
|
|
|
<el-radio :label="2">本月</el-radio> |
|
|
|
</el-radio-group> |
|
|
|
</el-radio-group> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</template> |
|
|
@ -114,8 +114,8 @@ |
|
|
|
:key="index" |
|
|
|
:key="index" |
|
|
|
> |
|
|
|
> |
|
|
|
<span class="mr-10px">NO.{{ index + 1 }}</span> |
|
|
|
<span class="mr-10px">NO.{{ index + 1 }}</span> |
|
|
|
<span class="mr-10px">{{ item.name }}</span> |
|
|
|
<span class="mr-10px">{{ item.username }}</span> |
|
|
|
<span>已跟进{{ item.count }}条线索</span> |
|
|
|
<span>已跟进{{ item.followNum }}条线索</span> |
|
|
|
</li> |
|
|
|
</li> |
|
|
|
<br /> |
|
|
|
<br /> |
|
|
|
<!-- </TransitionGroup> --> |
|
|
|
<!-- </TransitionGroup> --> |
|
|
@ -129,11 +129,11 @@ |
|
|
|
<div class="flex justify-between"> 本月成交榜Top10 </div> |
|
|
|
<div class="flex justify-between"> 本月成交榜Top10 </div> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
<el-skeleton :loading="loading" animated> |
|
|
|
<el-skeleton :loading="loading" animated> |
|
|
|
<el-table :data="followList" size="small"> |
|
|
|
<el-table :data="signList" size="small"> |
|
|
|
<el-table-column prop="sort" label="排名" width="50" /> |
|
|
|
<el-table-column type="index" /> |
|
|
|
<el-table-column prop="name" label="姓名" width="70" /> |
|
|
|
<el-table-column prop="username" label="姓名" width="100" /> |
|
|
|
<el-table-column prop="count" label="成交数量" width="70" /> |
|
|
|
<el-table-column prop="followNum" label="成交数量" width="70" /> |
|
|
|
<el-table-column prop="orgName" label="所属组织" /> |
|
|
|
<el-table-column prop="deptName" label="所属组织" /> |
|
|
|
</el-table> |
|
|
|
</el-table> |
|
|
|
</el-skeleton> |
|
|
|
</el-skeleton> |
|
|
|
</el-card> |
|
|
|
</el-card> |
|
|
@ -146,7 +146,8 @@ import { set } from 'lodash-es' |
|
|
|
import { EChartsOption } from 'echarts' |
|
|
|
import { EChartsOption } from 'echarts' |
|
|
|
import { useUserStore } from '@/store/modules/user' |
|
|
|
import { useUserStore } from '@/store/modules/user' |
|
|
|
import avatarImg from '@/assets/imgs/avatar.gif' |
|
|
|
import avatarImg from '@/assets/imgs/avatar.gif' |
|
|
|
import { pieOptions, lineOptions } from './echarts-data' |
|
|
|
import { lineOptions } from './echarts-data' |
|
|
|
|
|
|
|
import * as HomeApi from '@/api/home/index' |
|
|
|
|
|
|
|
|
|
|
|
const { t } = useI18n() |
|
|
|
const { t } = useI18n() |
|
|
|
const userStore = useUserStore() |
|
|
|
const userStore = useUserStore() |
|
|
@ -154,59 +155,46 @@ const loading = ref(false) |
|
|
|
const avatar = userStore.getUser.avatar ? userStore.getUser.avatar : avatarImg |
|
|
|
const avatar = userStore.getUser.avatar ? userStore.getUser.avatar : avatarImg |
|
|
|
const username = userStore.getUser.nickname |
|
|
|
const username = userStore.getUser.nickname |
|
|
|
|
|
|
|
|
|
|
|
const followDate = ref('day') |
|
|
|
const followDate = ref(1) |
|
|
|
|
|
|
|
|
|
|
|
// 成交线索来源 |
|
|
|
// 成交线索来源 |
|
|
|
const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption |
|
|
|
// const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption |
|
|
|
const getSaleClueSource = async () => { |
|
|
|
// const getSaleClueSource = async () => { |
|
|
|
const data = [ |
|
|
|
// const data = [ |
|
|
|
{ value: 335, name: '宝典' }, |
|
|
|
// { value: 335, name: '宝典' }, |
|
|
|
{ value: 310, name: '一点通' }, |
|
|
|
// { value: 310, name: '一点通' }, |
|
|
|
{ value: 234, name: '抖音' }, |
|
|
|
// { value: 234, name: '抖音' }, |
|
|
|
{ value: 135, name: '小红书' }, |
|
|
|
// { value: 135, name: '小红书' }, |
|
|
|
{ value: 1548, name: '转介绍' } |
|
|
|
// { value: 1548, name: '转介绍' } |
|
|
|
] |
|
|
|
// ] |
|
|
|
set( |
|
|
|
// set( |
|
|
|
pieOptionsData, |
|
|
|
// pieOptionsData, |
|
|
|
'legend.data', |
|
|
|
// 'legend.data', |
|
|
|
data.map((v) => t(v.name)) |
|
|
|
// data.map((v) => t(v.name)) |
|
|
|
) |
|
|
|
// ) |
|
|
|
pieOptionsData!.series![0].data = data.map((v) => { |
|
|
|
// pieOptionsData!.series![0].data = data.map((v) => { |
|
|
|
return { |
|
|
|
// return { |
|
|
|
name: t(v.name), |
|
|
|
// name: t(v.name), |
|
|
|
value: v.value |
|
|
|
// value: v.value |
|
|
|
} |
|
|
|
// } |
|
|
|
}) |
|
|
|
// }) |
|
|
|
} |
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
// 成交率 |
|
|
|
// 成交率 |
|
|
|
const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption |
|
|
|
const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption |
|
|
|
const getMonthlySaleRate = async () => { |
|
|
|
const getMonthlySaleRate = async () => { |
|
|
|
const data = [ |
|
|
|
const data = await HomeApi.getClueSignSignRate() |
|
|
|
{ estimate: 100, actual: 120, name: 'analysis.january' }, |
|
|
|
|
|
|
|
{ estimate: 120, actual: 82, name: 'analysis.february' }, |
|
|
|
|
|
|
|
{ estimate: 161, actual: 91, name: 'analysis.march' }, |
|
|
|
|
|
|
|
{ estimate: 134, actual: 154, name: 'analysis.april' }, |
|
|
|
|
|
|
|
{ estimate: 105, actual: 162, name: 'analysis.may' }, |
|
|
|
|
|
|
|
{ estimate: 160, actual: 140, name: 'analysis.june' }, |
|
|
|
|
|
|
|
{ estimate: 165, actual: 145, name: 'analysis.july' }, |
|
|
|
|
|
|
|
{ estimate: 114, actual: 250, name: 'analysis.august' }, |
|
|
|
|
|
|
|
{ estimate: 163, actual: 134, name: 'analysis.september' }, |
|
|
|
|
|
|
|
{ estimate: 185, actual: 56, name: 'analysis.october' }, |
|
|
|
|
|
|
|
{ estimate: 118, actual: 99, name: 'analysis.november' }, |
|
|
|
|
|
|
|
{ estimate: 123, actual: 123, name: 'analysis.december' } |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
set( |
|
|
|
set( |
|
|
|
lineOptionsData, |
|
|
|
lineOptionsData, |
|
|
|
'xAxis.data', |
|
|
|
'xAxis.data', |
|
|
|
data.map((v) => t(v.name)) |
|
|
|
data.map((v) => t(v.month)) |
|
|
|
) |
|
|
|
) |
|
|
|
set(lineOptionsData, 'series', [ |
|
|
|
set(lineOptionsData, 'series', [ |
|
|
|
{ |
|
|
|
{ |
|
|
|
name: '个人成交率', |
|
|
|
name: '个人成交率', |
|
|
|
smooth: true, |
|
|
|
smooth: true, |
|
|
|
type: 'line', |
|
|
|
type: 'line', |
|
|
|
data: data.map((v) => v.estimate), |
|
|
|
data: data.map((v) => v.personalRate), |
|
|
|
animationDuration: 2800, |
|
|
|
animationDuration: 2800, |
|
|
|
animationEasing: 'cubicInOut' |
|
|
|
animationEasing: 'cubicInOut' |
|
|
|
}, |
|
|
|
}, |
|
|
@ -215,33 +203,50 @@ const getMonthlySaleRate = async () => { |
|
|
|
smooth: true, |
|
|
|
smooth: true, |
|
|
|
type: 'line', |
|
|
|
type: 'line', |
|
|
|
itemStyle: {}, |
|
|
|
itemStyle: {}, |
|
|
|
data: data.map((v) => v.actual), |
|
|
|
data: data.map((v) => v.avgRate), |
|
|
|
animationDuration: 2800, |
|
|
|
animationDuration: 2800, |
|
|
|
animationEasing: 'quadraticOut' |
|
|
|
animationEasing: 'quadraticOut' |
|
|
|
} |
|
|
|
} |
|
|
|
]) |
|
|
|
]) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const followList = ref([ |
|
|
|
const followList = ref<any>([]) |
|
|
|
{ sort: 1, name: '张三', count: 12, orgName: '销售1组' }, |
|
|
|
|
|
|
|
{ sort: 2, name: '张三', count: 11, orgName: '销售3组' }, |
|
|
|
const clueInfo = ref({ |
|
|
|
{ sort: 3, name: '张三', count: 11, orgName: '销售1组' }, |
|
|
|
todayFollowingNum: 0, |
|
|
|
{ sort: 4, name: '张三', count: 10, orgName: '销售1组' }, |
|
|
|
todayFollowedNum: 0, |
|
|
|
{ sort: 5, name: '张三', count: 2, orgName: '销售2组' }, |
|
|
|
todaySignedNum: 0, |
|
|
|
{ sort: 6, name: '张三', count: 1, orgName: '销售1组' }, |
|
|
|
outFollowNum: 0, |
|
|
|
{ sort: 2, name: '张三', count: 11, orgName: '销售3组' }, |
|
|
|
unknownNum: 0 |
|
|
|
{ sort: 3, name: '张三', count: 11, orgName: '销售1组' }, |
|
|
|
}) |
|
|
|
{ sort: 4, name: '张三', count: 10, orgName: '销售1组' }, |
|
|
|
|
|
|
|
{ sort: 5, name: '张三', count: 2, orgName: '销售2组' }, |
|
|
|
function getClueInfo() { |
|
|
|
{ sort: 6, name: '张三', count: 1, orgName: '销售1组' } |
|
|
|
HomeApi.getUserClueCount().then((data) => { |
|
|
|
]) |
|
|
|
clueInfo.value = data |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getFollowList() { |
|
|
|
|
|
|
|
HomeApi.getClueFollowRank({ type: followDate.value }).then((data) => { |
|
|
|
|
|
|
|
followList.value = data |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const signList = ref([]) |
|
|
|
|
|
|
|
function getSignList() { |
|
|
|
|
|
|
|
HomeApi.getClueSignSignRank().then((data) => { |
|
|
|
|
|
|
|
signList.value = data |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const getAllApi = async () => { |
|
|
|
const getAllApi = async () => { |
|
|
|
await Promise.all([getSaleClueSource(), getMonthlySaleRate()]) |
|
|
|
await Promise.all([getClueInfo(), getSignList(), getMonthlySaleRate(), getFollowList()]) |
|
|
|
loading.value = false |
|
|
|
loading.value = false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => { |
|
|
|
getAllApi() |
|
|
|
getAllApi() |
|
|
|
|
|
|
|
}) |
|
|
|
</script> |
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped> |
|
|
|
<style lang="scss" scoped> |
|
|
|