You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
259 lines
8.1 KiB
259 lines
8.1 KiB
<template>
|
|
<div>
|
|
<el-card shadow="never">
|
|
<el-skeleton :loading="loading" animated>
|
|
<el-row :gutter="20" justify="space-between">
|
|
<el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
|
|
<div class="flex items-center">
|
|
<img :src="avatar" alt="" class="w-40px h-40px rounded-[50%] mr-20px" />
|
|
<div class="text-20px text-700">
|
|
{{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }}
|
|
</div>
|
|
</div>
|
|
</el-col>
|
|
<el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
|
|
<div class="flex h-40px items-center justify-end <sm:mt-10px">
|
|
<div class="px-8px text-right">
|
|
<div class="text-14px text-gray-400 mb-20px">今日待跟进</div>
|
|
<CountTo
|
|
class="text-20px number-font"
|
|
:start-val="0"
|
|
:end-val="clueInfo.todayFollowingNum"
|
|
:duration="2600"
|
|
/>
|
|
</div>
|
|
<el-divider direction="vertical" border-style="dashed" />
|
|
<div class="px-8px text-right">
|
|
<div class="text-14px text-gray-400 mb-20px">今日已跟进</div>
|
|
<CountTo
|
|
class="text-20px number-font"
|
|
:start-val="0"
|
|
:end-val="clueInfo.todayFollowedNum"
|
|
:duration="2600"
|
|
/>
|
|
</div>
|
|
<el-divider direction="vertical" border-style="dashed" />
|
|
<div class="px-8px text-right">
|
|
<div class="text-14px text-gray-400 mb-20px">今日已成交</div>
|
|
<CountTo
|
|
class="text-20px number-font"
|
|
:start-val="0"
|
|
:end-val="clueInfo.todaySignedNum"
|
|
:duration="2600"
|
|
/>
|
|
</div>
|
|
<el-divider direction="vertical" border-style="dashed" />
|
|
<div class="px-8px text-right">
|
|
<div class="text-14px text-gray-400 mb-20px">剩余过期数</div>
|
|
<CountTo
|
|
class="text-20px number-font"
|
|
:start-val="0"
|
|
:end-val="clueInfo.outFollowNum"
|
|
:duration="2600"
|
|
/>
|
|
</div>
|
|
<el-divider direction="vertical" border-style="dashed" />
|
|
<div class="px-8px text-right">
|
|
<div class="text-14px text-red-600 mb-20px">未知意向数</div>
|
|
<CountTo
|
|
class="text-20px number-font"
|
|
:start-val="0"
|
|
:end-val="clueInfo.unknownNum"
|
|
:duration="2600"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</el-col>
|
|
</el-row>
|
|
</el-skeleton>
|
|
</el-card>
|
|
<div class="mt-10px flex">
|
|
<el-card shadow="never" class="flex-1">
|
|
<template #header>
|
|
<div class="flex justify-between">
|
|
<span>成交率</span>
|
|
</div>
|
|
</template>
|
|
<el-skeleton :loading="loading" animated>
|
|
<el-skeleton :loading="loading" animated>
|
|
<Echart :options="lineOptionsData" :height="280" />
|
|
</el-skeleton>
|
|
</el-skeleton>
|
|
</el-card>
|
|
<el-card shadow="never" class="ml-10px">
|
|
<template #header>
|
|
<div class="flex justify-between items-center">
|
|
<span>跟进榜Top10</span>
|
|
<el-radio-group v-model="followDate" size="small" @change="getFollowList">
|
|
<el-radio :label="1">本日</el-radio>
|
|
<el-radio :label="2">本月</el-radio>
|
|
</el-radio-group>
|
|
</div>
|
|
</template>
|
|
<el-skeleton :loading="loading" animated>
|
|
<ul class="follow-wrap">
|
|
<!-- <TransitionGroup name="flip"> -->
|
|
<li
|
|
class="follow-item number-font mb-18px text-14px"
|
|
v-for="(item, index) in followList"
|
|
:key="index"
|
|
>
|
|
<span class="mr-10px">NO.{{ index + 1 }}</span>
|
|
<span class="mr-10px">{{ item.username }}</span>
|
|
<span>已跟进{{ item.followNum }}条线索</span>
|
|
</li>
|
|
<!-- <br /> -->
|
|
<!-- </TransitionGroup> -->
|
|
</ul>
|
|
</el-skeleton>
|
|
</el-card>
|
|
<el-card shadow="never" class="ml-10px">
|
|
<template #header>
|
|
<div class="flex justify-between"> 本月成交榜Top10 </div>
|
|
</template>
|
|
<el-skeleton :loading="loading" animated>
|
|
<el-table :data="signList" size="small">
|
|
<el-table-column type="index" />
|
|
<el-table-column prop="username" label="姓名" width="100" />
|
|
<el-table-column prop="followNum" label="成交数量" width="70" />
|
|
<el-table-column prop="deptName" label="所属组织" />
|
|
</el-table>
|
|
</el-skeleton>
|
|
</el-card>
|
|
</div>
|
|
<!-- <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24" class="mb-10px">
|
|
<el-card shadow="never">
|
|
<template #header>
|
|
<div class="flex justify-between ">
|
|
<span>本月成交来源</span>
|
|
</div>
|
|
</template>
|
|
<el-skeleton :loading="loading" animated>
|
|
<Echart :options="pieOptionsData" :height="280" />
|
|
</el-skeleton>
|
|
</el-card>
|
|
</el-col> -->
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts" name="Home">
|
|
import { set } from 'lodash-es'
|
|
import { EChartsOption } from 'echarts'
|
|
import { useUserStore } from '@/store/modules/user'
|
|
import avatarImg from '@/assets/imgs/avatar.gif'
|
|
import { lineOptions } from './echarts-data'
|
|
import * as HomeApi from '@/api/home/index'
|
|
|
|
const { t } = useI18n()
|
|
const userStore = useUserStore()
|
|
const loading = ref(false)
|
|
const avatar = userStore.getUser.avatar ? userStore.getUser.avatar : avatarImg
|
|
const username = userStore.getUser.nickname
|
|
|
|
const followDate = ref(1)
|
|
|
|
// 成交线索来源
|
|
// const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
|
|
// const getSaleClueSource = async () => {
|
|
// const data = [
|
|
// { value: 335, name: '宝典' },
|
|
// { value: 310, name: '一点通' },
|
|
// { value: 234, name: '抖音' },
|
|
// { value: 135, name: '小红书' },
|
|
// { value: 1548, name: '转介绍' }
|
|
// ]
|
|
// set(
|
|
// pieOptionsData,
|
|
// 'legend.data',
|
|
// data.map((v) => t(v.name))
|
|
// )
|
|
// pieOptionsData!.series![0].data = data.map((v) => {
|
|
// return {
|
|
// name: t(v.name),
|
|
// value: v.value
|
|
// }
|
|
// })
|
|
// }
|
|
|
|
// 成交率
|
|
const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption
|
|
const getMonthlySaleRate = async () => {
|
|
const data = await HomeApi.getClueSignSignRate()
|
|
set(
|
|
lineOptionsData,
|
|
'xAxis.data',
|
|
data.map((v) => t(v.month))
|
|
)
|
|
set(lineOptionsData, 'series', [
|
|
{
|
|
name: '个人成交率',
|
|
smooth: true,
|
|
type: 'line',
|
|
data: data.map((v) => v.personalRate),
|
|
animationDuration: 2800,
|
|
animationEasing: 'cubicInOut'
|
|
},
|
|
{
|
|
name: '平均成交率',
|
|
smooth: true,
|
|
type: 'line',
|
|
itemStyle: {},
|
|
data: data.map((v) => v.avgRate),
|
|
animationDuration: 2800,
|
|
animationEasing: 'quadraticOut'
|
|
}
|
|
])
|
|
}
|
|
|
|
const followList = ref<any>([])
|
|
|
|
const clueInfo = ref({
|
|
todayFollowingNum: 0,
|
|
todayFollowedNum: 0,
|
|
todaySignedNum: 0,
|
|
outFollowNum: 0,
|
|
unknownNum: 0
|
|
})
|
|
|
|
function getClueInfo() {
|
|
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 () => {
|
|
await Promise.all([getClueInfo(), getSignList(), getMonthlySaleRate(), getFollowList()])
|
|
loading.value = false
|
|
}
|
|
|
|
onMounted(() => {
|
|
getAllApi()
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@font-face {
|
|
font-family: numberFont;
|
|
src: url('@/assets/fonts/DISPLAY FREE TFB.ttf');
|
|
}
|
|
|
|
.number-font {
|
|
font-family: numberFont !important;
|
|
}
|
|
|
|
:deep(.el-card__header) {
|
|
padding: 10px;
|
|
}
|
|
</style>
|
|
|