【招生用户端】 新增# 工作台页面
parent
bb64589dfd
commit
a8cc9b437b
|
@ -52,4 +52,6 @@
|
||||||
--el-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, 0.12);
|
--el-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, 0.12);
|
||||||
--el-box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, 0.08), 0px 12px 32px rgba(0, 0, 0, 0.12), 0px 8px 16px -8px rgba(0, 0, 0, 0.16);
|
--el-box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, 0.08), 0px 12px 32px rgba(0, 0, 0, 0.12), 0px 8px 16px -8px rgba(0, 0, 0, 0.16);
|
||||||
--color-purple: #800080;
|
--color-purple: #800080;
|
||||||
|
--color-primary: #0e66fb;
|
||||||
|
--color-gray: #d5d5d5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col gap-[16px] bg-white p-[20px]">
|
<div class="flex flex-col gap-[16px] bg-white h-full">
|
||||||
<div class="flex-row-between-center">
|
<div class="flex-row-between-center px-[20px] pt-[20px]">
|
||||||
<span>{{ title }}</span>
|
<span class="text-[20px] font-bold">{{ title }}</span>
|
||||||
<slot name="right" />
|
<slot name="right" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="flex-1 px-[20px] pb-[20px]">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex-1 w-full">
|
||||||
|
<card title="线索转化情况统计">
|
||||||
|
<v-charts style="height: 350px" :option="option" :autoresize="true" />
|
||||||
|
</card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import card from './card.vue'
|
||||||
|
import vCharts from 'vue-echarts'
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ value: 1048, name: '有意向' },
|
||||||
|
{ value: 735, name: '待领取' },
|
||||||
|
{ value: 580, name: '转化中' },
|
||||||
|
{ value: 484, name: '已添加' },
|
||||||
|
{ value: 300, name: '异常待处理' },
|
||||||
|
{ value: 300, name: '已成交' },
|
||||||
|
{ value: 300, name: '已战败' }
|
||||||
|
]
|
||||||
|
const option = ref({
|
||||||
|
color: ['#73DDFF', '#73ACFF', '#FDD56A', '#FDB36A', '#FD866A', '#9E87FF', '#58D5FF'],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
top: 'center',
|
||||||
|
right: 0
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['25%', '55%'],
|
||||||
|
center: ['45%', '50%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'outside',
|
||||||
|
formatter: params => {
|
||||||
|
return `${params.name}:${params.percent}%`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,86 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex-1 w-full chart-card">
|
||||||
|
<card title="线索转客户统计">
|
||||||
|
<v-charts style="height: 350px" :autoresize="true" :option="option" />
|
||||||
|
</card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import card from './card.vue'
|
||||||
|
import vCharts from 'vue-echarts'
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ name: '湛江团队', clueNumber: 52, client: 52, rate: 100 },
|
||||||
|
{ name: '广州团队', clueNumber: 8, client: 6, rate: 15 }
|
||||||
|
]
|
||||||
|
function createBarSeries(data, name, field) {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
type: 'bar',
|
||||||
|
data: data.map(item => item[field])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLineSeries(data, name) {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
type: 'line',
|
||||||
|
tooltip: {
|
||||||
|
valueFormatter: function (value) {
|
||||||
|
return (value as number) + '%'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: data.map(item => item.client),
|
||||||
|
yAxisIndex: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const xAxisData = () => data.map(item => item.name)
|
||||||
|
const series = [
|
||||||
|
createBarSeries(data, '线索数', 'clueNumber'),
|
||||||
|
createBarSeries(data, '线索转客户数', 'client'),
|
||||||
|
createLineSeries(data, '线索转客户率')
|
||||||
|
]
|
||||||
|
|
||||||
|
const option = ref({
|
||||||
|
color: ['#0E66FB', '#FAC858', '#96B2D9'],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross',
|
||||||
|
crossStyle: {
|
||||||
|
color: '#999'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toolbox: {},
|
||||||
|
legend: {},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
data: xAxisData()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value} %'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@media (max-width: 1000px) {
|
||||||
|
.chart-card {
|
||||||
|
flex: 1 0 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,63 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex-1 w-full chart-card">
|
||||||
|
<card title="成交客户统计">
|
||||||
|
<v-charts style="height: 350px" :autoresize="true" :option="option" />
|
||||||
|
</card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import card from './card.vue'
|
||||||
|
import vCharts from 'vue-echarts'
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ name: '湛江团队', clueNumber: 52, client: 52, rate: 100 },
|
||||||
|
{ name: '广州团队', clueNumber: 8, client: 6, rate: 15 }
|
||||||
|
]
|
||||||
|
function createBarSeries(data, name, field) {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
type: 'bar',
|
||||||
|
data: data.map(item => item[field])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const xAxisData = () => data.map(item => item.name)
|
||||||
|
const series = [createBarSeries(data, '客户数', 'clueNumber'), createBarSeries(data, '成交客户数', 'client')]
|
||||||
|
|
||||||
|
const option = ref({
|
||||||
|
color: ['#0E66FB', '#96B2D9'],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross',
|
||||||
|
crossStyle: {
|
||||||
|
color: '#999'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toolbox: {},
|
||||||
|
legend: {},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
data: xAxisData()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@media (max-width: 1000px) {
|
||||||
|
.chart-card {
|
||||||
|
flex: 1 0 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex-1 w-full">
|
||||||
|
<card title="成交客户增长趋势">
|
||||||
|
<v-charts style="height: 350px" :option="option" :autoresize="true" />
|
||||||
|
</card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import vCharts from 'vue-echarts'
|
||||||
|
import card from './card.vue'
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ label: '2025-02-24', value: 320 },
|
||||||
|
{ label: '2025-02-25', value: 132 },
|
||||||
|
{ label: '2025-02-26', value: 201 },
|
||||||
|
{ label: '2025-02-27', value: 334 },
|
||||||
|
{ label: '2025-02-28', value: 190 },
|
||||||
|
{ label: '2025-03-01', value: 130 },
|
||||||
|
{ label: '2025-03-02', value: 220 }
|
||||||
|
]
|
||||||
|
const xAxisData = data.map(item => item.label)
|
||||||
|
const seriesData = data.map(item => item.value)
|
||||||
|
const option = ref({
|
||||||
|
color: ['#37A2FF'],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis'
|
||||||
|
},
|
||||||
|
legend: {},
|
||||||
|
toolbox: {},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: xAxisData,
|
||||||
|
axisLabel: {
|
||||||
|
interval: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '成交客户数量',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
areaStyle: {
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: '#9E87FFb3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: '#9E87FF03'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: seriesData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
|
@ -1,10 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<card title="数据简报">
|
<card title="数据简报">
|
||||||
<div>333</div>
|
<div class="data-overview">
|
||||||
|
<div
|
||||||
|
class="flex-1 bg-[#F7F8FA] flex flex-col gap-[12px] p-[20px] rounded-[8px]"
|
||||||
|
v-for="(item, index) in dataOverview"
|
||||||
|
:key="`unique-${index}`"
|
||||||
|
>
|
||||||
|
<span>{{ item.label }}</span>
|
||||||
|
<span class="text-[20px]">{{ item.value }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</card>
|
</card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import card from './card.vue'
|
import card from './card.vue'
|
||||||
|
const dataOverview = ref([
|
||||||
|
{ label: '新增跟进记录(个)', value: 60 },
|
||||||
|
{ label: '新增客户(个)', value: 60 },
|
||||||
|
{ label: '成交客户(个)', value: 60 },
|
||||||
|
{ label: '转化中客户(个)', value: 60 },
|
||||||
|
{ label: '异常待处理(个)', value: 60 },
|
||||||
|
{ label: '战败客户(个)', value: 60 }
|
||||||
|
])
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
<style scoped lang="scss">
|
||||||
|
.data-overview {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
<template>
|
||||||
|
<div class="rank flex-1">
|
||||||
|
<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">
|
||||||
|
{{ 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>
|
||||||
|
</card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import card from './card.vue'
|
||||||
|
const positions = ref([
|
||||||
|
{ name: '电销', id: 5 },
|
||||||
|
{ name: '招生', id: 6 }
|
||||||
|
])
|
||||||
|
const postId = ref(5)
|
||||||
|
|
||||||
|
const tableData = ref([
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
name: 'John Brown',
|
||||||
|
totalNumber: 32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 2,
|
||||||
|
name: 'John Brown',
|
||||||
|
totalNumber: 32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 3,
|
||||||
|
name: 'John Brown',
|
||||||
|
totalNumber: 32
|
||||||
|
}
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.rank {
|
||||||
|
min-height: 350px;
|
||||||
|
.positions {
|
||||||
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
span {
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: 1px solid var(--color-gray);
|
||||||
|
&:first-child {
|
||||||
|
border-right-color: transparent;
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
border-left-color: transparent;
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
color: var(--color-primary);
|
||||||
|
border-color: var(--color-primary);
|
||||||
|
border-right-color: var(--color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,91 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="workbench">
|
<div class="workbench flex flex-col gap-[16px]">
|
||||||
<data-overview />
|
<data-overview />
|
||||||
<div class="mb-4 function">2</div>
|
<div class="flex gap-[16px] flex-wrap">
|
||||||
<div class="lg:flex">
|
<conversion-process-chart />
|
||||||
<el-card class="flex-1 !border-none md:mr-4 mb-4" shadow="never">
|
<converted-chart />
|
||||||
<template #header>
|
</div>
|
||||||
<span>销售额趋势图(近15天)</span>
|
<div class="flex gap-[16px] flex-wrap">
|
||||||
</template>
|
<rank />
|
||||||
<div>
|
<clue-status-pie />
|
||||||
<v-charts style="height: 350px" :option="workbenchData.businessOption" :autoresize="true" />
|
<!-- <converted-line-chart /> -->
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<el-card class="flex-1 !border-none md:mr-4 mb-4" shadow="never">
|
|
||||||
<template #header>
|
|
||||||
<span>用户访问量(近15天)</span>
|
|
||||||
</template>
|
|
||||||
<div>
|
|
||||||
<v-charts style="height: 350px" :option="workbenchData.visitorOption" :autoresize="true" />
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import dataOverview from './components/data-overview.vue'
|
import dataOverview from './components/data-overview.vue'
|
||||||
import vCharts from 'vue-echarts'
|
import conversionProcessChart from './components/conversion-process-chart.vue'
|
||||||
// 表单数据
|
import convertedChart from './components/converted-chart.vue'
|
||||||
const workbenchData: any = reactive({
|
import rank from './components/rank.vue'
|
||||||
businessOption: {
|
import clueStatusPie from './components/clue-status-pie.vue'
|
||||||
xAxis: {
|
// import convertedLineChart from './components/converted-line-chart.vue'
|
||||||
type: 'category',
|
|
||||||
data: []
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value'
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
// 点的颜色。
|
|
||||||
color: 'red'
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '销售量',
|
|
||||||
data: [],
|
|
||||||
type: 'line',
|
|
||||||
smooth: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
visitorOption: {
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
data: []
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value'
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
// 点的颜色。
|
|
||||||
color: 'red'
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '访问量',
|
|
||||||
data: [],
|
|
||||||
type: 'line',
|
|
||||||
smooth: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取工作台主页数据
|
|
||||||
const getData = async () => {}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getData()
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped>
|
||||||
|
.wokrbench {
|
||||||
|
&-center {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue