初始化

This commit is contained in:
qsh
2024-04-28 16:20:45 +08:00
parent 3f2749b6c4
commit 58929c05ef
687 changed files with 90151 additions and 13 deletions

258
src/views/Home/Index.vue Normal file
View File

@@ -0,0 +1,258 @@
<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="10"
: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="25"
: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="2"
: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="235"
: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="0"
:duration="2600"
/>
</div>
</div>
</el-col>
</el-row>
</el-skeleton>
</el-card>
<el-row class="mt-10px" :gutter="10" justify="space-between">
<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 h-3">
<span>本月成交来源</span>
</div>
</template>
<el-skeleton :loading="loading" animated>
<Echart :options="pieOptionsData" :height="280" />
</el-skeleton>
</el-card>
</el-col>
<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 h-3">
<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-col>
<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 h-3">
<span>跟进榜Top10</span>
<el-radio-group v-model="followDate" size="small">
<el-radio label="day">本日</el-radio>
<el-radio label="month">本月</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.name }}</span>
<span>已跟进{{ item.count }}条线索</span>
</li>
<br />
<!-- </TransitionGroup> -->
</ul>
</el-skeleton>
</el-card>
</el-col>
<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 h-3">
<span>本月成交榜Top10</span>
</div>
</template>
<el-skeleton :loading="loading" animated>
<el-table :data="followList" size="small">
<el-table-column prop="sort" label="排名" width="50" />
<el-table-column prop="name" label="姓名" width="70" />
<el-table-column prop="count" label="跟进数量" width="70" />
<el-table-column prop="orgName" label="所属组织" />
</el-table>
</el-skeleton>
</el-card>
</el-col>
</el-row>
</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 { pieOptions, lineOptions } from './echarts-data'
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('day')
// 成交线索来源
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 = [
{ 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(
lineOptionsData,
'xAxis.data',
data.map((v) => t(v.name))
)
set(lineOptionsData, 'series', [
{
name: t('analysis.estimate'),
smooth: true,
type: 'line',
data: data.map((v) => v.estimate),
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: t('analysis.actual'),
smooth: true,
type: 'line',
itemStyle: {},
data: data.map((v) => v.actual),
animationDuration: 2800,
animationEasing: 'quadraticOut'
}
])
}
const followList = ref([
{ sort: 1, name: '张三', count: 12, orgName: '销售1组' },
{ sort: 2, name: '张三', count: 11, orgName: '销售3组' },
{ sort: 3, name: '张三', count: 11, orgName: '销售1组' },
{ sort: 4, name: '张三', count: 10, orgName: '销售1组' },
{ sort: 5, name: '张三', count: 2, orgName: '销售2组' },
{ sort: 6, name: '张三', count: 1, orgName: '销售1组' },
{ sort: 2, name: '张三', count: 11, orgName: '销售3组' },
{ sort: 3, name: '张三', count: 11, orgName: '销售1组' },
{ sort: 4, name: '张三', count: 10, orgName: '销售1组' },
{ sort: 5, name: '张三', count: 2, orgName: '销售2组' },
{ sort: 6, name: '张三', count: 1, orgName: '销售1组' }
])
const getAllApi = async () => {
await Promise.all([getSaleClueSource(), getMonthlySaleRate()])
loading.value = false
}
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;
}
</style>

View File

@@ -0,0 +1,7 @@
<template>
<div> </div>
</template>
<script setup></script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,285 @@
import { EChartsOption } from 'echarts'
const { t } = useI18n()
export const lineOptions: EChartsOption = {
xAxis: {
data: [
t('analysis.january'),
t('analysis.february'),
t('analysis.march'),
t('analysis.april'),
t('analysis.may'),
t('analysis.june'),
t('analysis.july'),
t('analysis.august'),
t('analysis.september'),
t('analysis.october'),
t('analysis.november'),
t('analysis.december')
],
boundaryGap: false,
axisTick: {
show: false
}
},
grid: {
left: 20,
right: 20,
bottom: 20,
top: 80,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
yAxis: {
axisTick: {
show: false
}
},
series: [
{
name: '成交率',
smooth: true,
type: 'line',
data: [100, 120, 161, 134, 105, 160, 165, 114, 163, 185, 118, 123],
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: t('analysis.actual'),
smooth: true,
type: 'line',
itemStyle: {},
data: [120, 82, 91, 154, 162, 140, 145, 250, 134, 56, 99, 123],
animationDuration: 2800,
animationEasing: 'quadraticOut'
}
]
}
export const pieOptions: EChartsOption = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
series: [
{
name: '成交来源',
type: 'pie',
radius: '35%',
center: ['50%', '80%'],
data: [
{ value: 335, name: '宝典' },
{ value: 310, name: '一点通' },
{ value: 234, name: '抖音' },
{ value: 135, name: '小红书' },
{ value: 1548, name: '转介绍' }
]
}
]
}
export const barOptions: EChartsOption = {
title: {
text: t('analysis.weeklyUserActivity'),
left: 'center'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: 50,
right: 20,
bottom: 20
},
xAxis: {
type: 'category',
data: [
t('analysis.monday'),
t('analysis.tuesday'),
t('analysis.wednesday'),
t('analysis.thursday'),
t('analysis.friday'),
t('analysis.saturday'),
t('analysis.sunday')
],
axisTick: {
alignWithLabel: true
}
},
yAxis: {
type: 'value'
},
series: [
{
name: t('analysis.activeQuantity'),
data: [13253, 34235, 26321, 12340, 24643, 1322, 1324],
type: 'bar'
}
]
}
export const radarOption: EChartsOption = {
legend: {
data: [t('workplace.personal'), t('workplace.team')]
},
radar: {
// shape: 'circle',
indicator: [
{ name: t('workplace.quote'), max: 65 },
{ name: t('workplace.contribution'), max: 160 },
{ name: t('workplace.hot'), max: 300 },
{ name: t('workplace.yield'), max: 130 },
{ name: t('workplace.follow'), max: 100 }
]
},
series: [
{
name: `xxx${t('workplace.index')}`,
type: 'radar',
data: [
{
value: [42, 30, 20, 35, 80],
name: t('workplace.personal')
},
{
value: [50, 140, 290, 100, 90],
name: t('workplace.team')
}
]
}
]
}
export const wordOptions = {
series: [
{
type: 'wordCloud',
gridSize: 2,
sizeRange: [12, 50],
rotationRange: [-90, 90],
shape: 'pentagon',
width: 600,
height: 400,
drawOutOfBound: true,
textStyle: {
color: function () {
return (
'rgb(' +
[
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160)
].join(',') +
')'
)
}
},
emphasis: {
textStyle: {
shadowBlur: 10,
shadowColor: '#333'
}
},
data: [
{
name: 'Sam S Club',
value: 10000,
textStyle: {
color: 'black'
},
emphasis: {
textStyle: {
color: 'red'
}
}
},
{
name: 'Macys',
value: 6181
},
{
name: 'Amy Schumer',
value: 4386
},
{
name: 'Jurassic World',
value: 4055
},
{
name: 'Charter Communications',
value: 2467
},
{
name: 'Chick Fil A',
value: 2244
},
{
name: 'Planet Fitness',
value: 1898
},
{
name: 'Pitch Perfect',
value: 1484
},
{
name: 'Express',
value: 1112
},
{
name: 'Home',
value: 965
},
{
name: 'Johnny Depp',
value: 847
},
{
name: 'Lena Dunham',
value: 582
},
{
name: 'Lewis Hamilton',
value: 555
},
{
name: 'KXAN',
value: 550
},
{
name: 'Mary Ellen Mark',
value: 462
},
{
name: 'Farrah Abraham',
value: 366
},
{
name: 'Rita Ora',
value: 360
},
{
name: 'Serena Williams',
value: 282
},
{
name: 'NCAA baseball tournament',
value: 273
},
{
name: 'Point Break',
value: 265
}
]
}
]
}

View File

@@ -0,0 +1,7 @@
<template>
<div> </div>
</template>
<script setup></script>
<style lang="scss" scoped></style>