dev-cl
parent
fa39fd8492
commit
0ef7703f7d
@ -0,0 +1,62 @@ |
|||||||
|
<template> |
||||||
|
<Echart :options="optionsData" :width="400" :height="200" /> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="BarSalerClueReport"> |
||||||
|
import { set } from 'lodash-es' |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
nextTick(() => { |
||||||
|
getReportData() |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
const optionsData = ref({}) |
||||||
|
|
||||||
|
const getReportData = async () => { |
||||||
|
// const data = await HomeApi.getClueSignSignRate() |
||||||
|
set(optionsData, 'radiusAxis', { |
||||||
|
type: 'category', |
||||||
|
data: ['宝典', '一点通', '抖音', '小红书'], |
||||||
|
z: 10 |
||||||
|
}) |
||||||
|
set(optionsData, 'series', [ |
||||||
|
{ |
||||||
|
type: 'bar', |
||||||
|
data: [1, 2, 3, 4], |
||||||
|
coordinateSystem: 'polar', |
||||||
|
name: '高意向A', |
||||||
|
stack: 'a', |
||||||
|
emphasis: { |
||||||
|
focus: 'series' |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: 'bar', |
||||||
|
data: [2, 4, 6, 8], |
||||||
|
coordinateSystem: 'polar', |
||||||
|
name: '中意向B', |
||||||
|
stack: 'a', |
||||||
|
emphasis: { |
||||||
|
focus: 'series' |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: 'bar', |
||||||
|
data: [1, 2, 3, 4], |
||||||
|
coordinateSystem: 'polar', |
||||||
|
name: '低意向C', |
||||||
|
stack: 'a', |
||||||
|
emphasis: { |
||||||
|
focus: 'series' |
||||||
|
} |
||||||
|
} |
||||||
|
]) |
||||||
|
} |
||||||
|
|
||||||
|
defineExpose({ |
||||||
|
getReportData |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,353 @@ |
|||||||
|
<template> |
||||||
|
<Dialog title="详情" v-model="dialogVisible" width="1000px"> |
||||||
|
<el-form :model="searchForm" label-width="0" inline> |
||||||
|
<el-form-item> |
||||||
|
<el-date-picker |
||||||
|
v-model="searchForm.period" |
||||||
|
type="daterange" |
||||||
|
format="YYYY-MM-DD" |
||||||
|
value-format="YYYY-MM-DD" |
||||||
|
start-placeholder="选择日期" |
||||||
|
end-placeholder="选择日期" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-tree-select |
||||||
|
v-model="searchForm.sourceId" |
||||||
|
:data="props.sourceOptions" |
||||||
|
:props="defaultProps" |
||||||
|
check-strictly |
||||||
|
node-key="sourceId" |
||||||
|
placeholder="请选择渠道" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-select v-model="searchForm.cartype" placeholder="选择驾照类型" clearable> |
||||||
|
<el-option |
||||||
|
v-for="item in props.cartypeOptions" |
||||||
|
:key="item.value" |
||||||
|
:label="item.label" |
||||||
|
:value="item.value" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item> |
||||||
|
<el-button @click="handleSearch">查询</el-button> |
||||||
|
<el-button @click="handleReset">重置</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
|
||||||
|
<el-tabs v-model="showPane" class="pb-10px"> |
||||||
|
<el-tab-pane label="详细数据" :name="1"> |
||||||
|
<el-table v-loading="loading" :data="tableList" border stripe> |
||||||
|
<el-table-column prop="sourceName" label="渠道名称" width="100" fixed="left" /> |
||||||
|
<el-table-column prop="" label="新线索数" sortable /> |
||||||
|
<el-table-column prop="" label="成交数" sortable /> |
||||||
|
<el-table-column prop="" label="成交率" sortable /> |
||||||
|
<el-table-column prop="" label="成交周期" sortable /> |
||||||
|
<el-table-column prop="" label="毛利/单" sortable /> |
||||||
|
<el-table-column prop="" label="支出/单" sortable /> |
||||||
|
<el-table-column prop="" label="线索成本/条" sortable /> |
||||||
|
<el-table-column prop="" label="净利润/单" sortable /> |
||||||
|
<el-table-column label="总线索成本" prop="" sortable min-width="100" /> |
||||||
|
<el-table-column label="总支出" prop="" sortable min-width="100" /> |
||||||
|
<el-table-column label="总利润" prop="" sortable min-width="100" /> |
||||||
|
</el-table> |
||||||
|
</el-tab-pane> |
||||||
|
<el-tab-pane label="图表展示" :name="2" lazy> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="24" :offset="0"> |
||||||
|
<el-checkbox-group v-model="showChannel" @change="setReportData"> |
||||||
|
<el-checkbox v-for="(item, index) in channelArr" :key="index" :label="item" /> |
||||||
|
</el-checkbox-group> |
||||||
|
</el-col> |
||||||
|
|
||||||
|
<el-col :span="12" :offset="0"> |
||||||
|
<el-skeleton :loading="loading" animated> |
||||||
|
<Echart :options="echart1Option" width="100%" :height="400" /> |
||||||
|
</el-skeleton> |
||||||
|
</el-col> |
||||||
|
<el-col :span="12" :offset="0"> |
||||||
|
<Echart :options="echart2Option" width="100%" :height="400" /> |
||||||
|
</el-col> |
||||||
|
<el-col :span="24" :offset="0"> |
||||||
|
<Echart :options="echart3Option" width="100%" :height="400" /> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
</el-tab-pane> |
||||||
|
</el-tabs> |
||||||
|
</Dialog> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="DialogSalerReportDetail"> |
||||||
|
import { set } from 'lodash-es' |
||||||
|
import * as reportApi from '@/api/home/reportSignRate' |
||||||
|
import { removeNullField } from '@/utils' |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
cartypeOptions: { |
||||||
|
type: Array, |
||||||
|
default: () => [] |
||||||
|
}, |
||||||
|
sourceOptions: { |
||||||
|
type: Array, |
||||||
|
default: () => [] |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
const defaultProps = { |
||||||
|
children: 'children', |
||||||
|
label: 'sourceName', |
||||||
|
value: 'sourceId', |
||||||
|
isLeaf: 'leaf' |
||||||
|
} |
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示 |
||||||
|
const dialogTitle = ref('') // 弹窗的标题 |
||||||
|
const loading = ref(false) |
||||||
|
const searchForm = ref({}) |
||||||
|
|
||||||
|
const showPane = ref(1) |
||||||
|
const showChannel = ref([]) |
||||||
|
|
||||||
|
function handleReset() { |
||||||
|
searchForm.value = { |
||||||
|
nickname: undefined, |
||||||
|
period: [] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 打开弹窗 */ |
||||||
|
const open = async (info, queryInfo) => { |
||||||
|
showPane.value = 1 |
||||||
|
dialogVisible.value = true |
||||||
|
dialogTitle.value = `销售详情-【${info.nickname}】` |
||||||
|
searchForm.value.period = queryInfo.period |
||||||
|
searchForm.value.cartype = queryInfo.cartype |
||||||
|
showChannel.value = [...channelArr] |
||||||
|
|
||||||
|
handleSearch() |
||||||
|
} |
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
||||||
|
|
||||||
|
const tableList = ref([]) |
||||||
|
|
||||||
|
async function handleSearch() { |
||||||
|
loading.value = true |
||||||
|
try { |
||||||
|
setReportData() |
||||||
|
const data = await reportApi.getList(removeNullField(searchForm.value)) |
||||||
|
tableList.value = data.map((item) => { |
||||||
|
const count = item.monthClueSignRateReportList.reduce( |
||||||
|
(pre, cur) => { |
||||||
|
return { |
||||||
|
signCount: pre.signCount + cur.clueSignNum, |
||||||
|
clueCount: pre.clueCount + cur.followClueNum |
||||||
|
} |
||||||
|
}, |
||||||
|
{ signCount: 0, clueCount: 0 } |
||||||
|
) |
||||||
|
const rate = count.clueCount > 0 ? ((count.signCount * 100) / count.clueCount).toFixed(2) : 0 |
||||||
|
return { |
||||||
|
...item, |
||||||
|
totalRate: `${rate}%(${count.signCount}/${count.clueCount})`, |
||||||
|
totalRateNum: rate |
||||||
|
} |
||||||
|
}) |
||||||
|
} finally { |
||||||
|
loading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const channelArr = ['美团', '高德', '线下渠道', '其他', '一点通', '抖音', '小红书', '宝典'] |
||||||
|
|
||||||
|
const echart1Option = ref({ |
||||||
|
title: { |
||||||
|
text: '线索分布图' |
||||||
|
}, |
||||||
|
radiusAxis: {}, |
||||||
|
angleAxis: {}, |
||||||
|
tooltip: { |
||||||
|
show: true, |
||||||
|
formatter: '{b0}-{a}: {c}' |
||||||
|
}, |
||||||
|
polar: {}, |
||||||
|
legend: { |
||||||
|
show: true |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
const echart2Option = ref({ |
||||||
|
title: { |
||||||
|
text: '成交分布图' |
||||||
|
}, |
||||||
|
radiusAxis: {}, |
||||||
|
angleAxis: {}, |
||||||
|
tooltip: { |
||||||
|
show: true, |
||||||
|
formatter: '{b0}-{a}: {c}' |
||||||
|
}, |
||||||
|
polar: {}, |
||||||
|
legend: { |
||||||
|
show: true |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
const echart3Option = ref({ |
||||||
|
title: { |
||||||
|
text: '销售雷达图' |
||||||
|
}, |
||||||
|
radar: { |
||||||
|
indicator: [ |
||||||
|
{ name: '成交周期' }, |
||||||
|
{ name: '毛利/单' }, |
||||||
|
{ name: '支出/单' }, |
||||||
|
{ name: '线索成本/条' }, |
||||||
|
{ name: '净利润/单' }, |
||||||
|
{ name: '线索总成本' }, |
||||||
|
{ name: '总支出' }, |
||||||
|
{ name: '总利润' } |
||||||
|
] |
||||||
|
}, |
||||||
|
legend: { |
||||||
|
show: true |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
const setReportData = async () => { |
||||||
|
// const data = await HomeApi.getClueSignSignRate() |
||||||
|
|
||||||
|
set(echart1Option.value, 'radiusAxis', { |
||||||
|
type: 'category', |
||||||
|
data: showChannel.value, |
||||||
|
axisLabel: { |
||||||
|
margin: 5, |
||||||
|
fontSize: 10, |
||||||
|
interval: 0 |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
set(echart1Option.value, 'series', [ |
||||||
|
{ |
||||||
|
type: 'bar', |
||||||
|
data: [2, 2, 3, 4, 10, 22, 43, 141], |
||||||
|
coordinateSystem: 'polar', |
||||||
|
name: '高意向A', |
||||||
|
stack: 'a', |
||||||
|
emphasis: { |
||||||
|
focus: 'series' |
||||||
|
}, |
||||||
|
label: { |
||||||
|
show: true, |
||||||
|
position: 'middle' |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: 'bar', |
||||||
|
data: [6, 6, 7, 8, 22, 14, 36, 128], |
||||||
|
coordinateSystem: 'polar', |
||||||
|
name: '中意向B', |
||||||
|
stack: 'a', |
||||||
|
emphasis: { |
||||||
|
focus: 'series' |
||||||
|
}, |
||||||
|
label: { |
||||||
|
show: true, |
||||||
|
position: 'middle' |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: 'bar', |
||||||
|
data: [1, 4, 7, 11, 16, 42, 13, 42], |
||||||
|
coordinateSystem: 'polar', |
||||||
|
name: '低意向C', |
||||||
|
stack: 'a', |
||||||
|
emphasis: { |
||||||
|
focus: 'series' |
||||||
|
}, |
||||||
|
label: { |
||||||
|
show: true, |
||||||
|
position: 'middle' |
||||||
|
} |
||||||
|
} |
||||||
|
]) |
||||||
|
|
||||||
|
set(echart2Option.value, 'radiusAxis', { |
||||||
|
type: 'category', |
||||||
|
data: showChannel.value, |
||||||
|
axisLabel: { |
||||||
|
margin: 5, |
||||||
|
fontSize: 10, |
||||||
|
interval: 0 |
||||||
|
} |
||||||
|
}) |
||||||
|
set(echart2Option.value, 'series', [ |
||||||
|
{ |
||||||
|
type: 'bar', |
||||||
|
data: [2, 2, 3, 4, 1, 11, 23, 41], |
||||||
|
coordinateSystem: 'polar', |
||||||
|
name: 'C1', |
||||||
|
stack: 'a', |
||||||
|
emphasis: { |
||||||
|
focus: 'series' |
||||||
|
}, |
||||||
|
label: { |
||||||
|
show: true, |
||||||
|
position: 'middle' |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: 'bar', |
||||||
|
data: [6, 6, 7, 8, 12, 14, 6, 28], |
||||||
|
coordinateSystem: 'polar', |
||||||
|
name: 'C2', |
||||||
|
stack: 'a', |
||||||
|
emphasis: { |
||||||
|
focus: 'series' |
||||||
|
}, |
||||||
|
label: { |
||||||
|
show: true, |
||||||
|
position: 'middle' |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: 'bar', |
||||||
|
data: [1, 4, 7, 1, 6, 2, 23, 14], |
||||||
|
coordinateSystem: 'polar', |
||||||
|
name: 'D/E/F', |
||||||
|
stack: 'a', |
||||||
|
emphasis: { |
||||||
|
focus: 'series' |
||||||
|
}, |
||||||
|
label: { |
||||||
|
show: true, |
||||||
|
position: 'middle' |
||||||
|
} |
||||||
|
} |
||||||
|
]) |
||||||
|
set(echart3Option.value, 'series', [ |
||||||
|
{ |
||||||
|
type: 'radar', |
||||||
|
data: [ |
||||||
|
{ |
||||||
|
value: [5.5, 1000, 200, 51, 666, 12345, 1245, 65478], |
||||||
|
name: '平均', |
||||||
|
label: { |
||||||
|
show: true |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: [15, 800, 300, 66, 551, 23456, 2123, 25698], |
||||||
|
name: '当前', |
||||||
|
label: { |
||||||
|
show: true |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
]) |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
Loading…
Reference in new issue