|
@@ -1,18 +1,74 @@
|
|
|
<script lang="ts" setup>
|
|
|
-import { ref, reactive } from 'vue';
|
|
|
+import { ref, reactive, onMounted, watchEffect } from 'vue';
|
|
|
import TrendCard from './components/TrendCard.vue';
|
|
|
import SimpleCard from './components/SimpleCard.vue';
|
|
|
import Divider from './components/Divider.vue';
|
|
|
import Echarts from '@/components/ReEcharts/index.vue';
|
|
|
import { EChartsOption } from 'echarts';
|
|
|
+import { dayjs } from 'element-plus';
|
|
|
+import {
|
|
|
+ getSummaryData,
|
|
|
+ getBulletinData,
|
|
|
+ BulletinData,
|
|
|
+ getStageData,
|
|
|
+ RequestProps,
|
|
|
+ StageData,
|
|
|
+ SummaryData
|
|
|
+} from './api';
|
|
|
|
|
|
-const prompt = reactive({ summary: {}, stage: {}, bulletin: {} });
|
|
|
+const permissionOptions = [
|
|
|
+ {
|
|
|
+ label: '仅本人',
|
|
|
+ value: 0
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '本人及下属',
|
|
|
+ value: 1
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '仅本部门',
|
|
|
+ value: 2
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '本部门及下属部门',
|
|
|
+ value: 3
|
|
|
+ }
|
|
|
+];
|
|
|
+const dateOptions = [
|
|
|
+ {
|
|
|
+ label: '本月',
|
|
|
+ value: 0
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '本周',
|
|
|
+ value: 1
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '本年',
|
|
|
+ value: 2
|
|
|
+ }
|
|
|
+];
|
|
|
|
|
|
-const option: EChartsOption = {
|
|
|
+const defineDate = ref<[Date, Date] | ''>('');
|
|
|
+
|
|
|
+const bulletinPrompt = reactive({ permission: undefined, date: undefined });
|
|
|
+const summaryPrompt = reactive({ permission: undefined, date: undefined });
|
|
|
+const stagePrompt = reactive({ permission: undefined, date: undefined });
|
|
|
+
|
|
|
+const requestData = reactive<{
|
|
|
+ bulletin: BulletinData['data'] | null;
|
|
|
+ summary: SummaryData['data'] | null;
|
|
|
+ stage: StageData['data'] | null;
|
|
|
+}>({
|
|
|
+ summary: null,
|
|
|
+ stage: null,
|
|
|
+ bulletin: null
|
|
|
+});
|
|
|
+
|
|
|
+const chartOptions: EChartsOption = reactive({
|
|
|
grid: { top: 0, bottom: 20, left: 60 },
|
|
|
yAxis: {
|
|
|
- type: 'category',
|
|
|
- data: ['验证客户', '赢单', '输单']
|
|
|
+ type: 'category'
|
|
|
},
|
|
|
xAxis: {
|
|
|
type: 'value'
|
|
@@ -20,11 +76,67 @@ const option: EChartsOption = {
|
|
|
series: [
|
|
|
{
|
|
|
barWidth: 20,
|
|
|
- data: [0, 20, 40, 60, 80, 100],
|
|
|
+ data: [10, 30, 30, 30, 30],
|
|
|
type: 'bar'
|
|
|
}
|
|
|
]
|
|
|
+});
|
|
|
+
|
|
|
+const queryBulletin = async (payload?: RequestProps) => {
|
|
|
+ const bulletinResult = await getBulletinData(payload);
|
|
|
+ requestData.bulletin = bulletinResult.data;
|
|
|
};
|
|
|
+
|
|
|
+const querySummary = async (payload?: RequestProps) => {
|
|
|
+ const summaryResult = await getSummaryData(payload);
|
|
|
+ requestData.summary = summaryResult.data;
|
|
|
+};
|
|
|
+
|
|
|
+const queryStage = async (payload?: RequestProps) => {
|
|
|
+ const stageResult = await getStageData(payload);
|
|
|
+ const data = stageResult.data;
|
|
|
+
|
|
|
+ // @ts-ignore
|
|
|
+ chartOptions.yAxis.data = data.dataMap.map((map) => map.stageName);
|
|
|
+ // @ts-ignore
|
|
|
+ chartOptions.series[0].data = data.dataMap.map((map) => map.num);
|
|
|
+};
|
|
|
+
|
|
|
+watchEffect(() => {
|
|
|
+ queryBulletin({
|
|
|
+ ...(bulletinPrompt.date === 'defineDate'
|
|
|
+ ? {
|
|
|
+ startDate: dayjs(defineDate.value[0]).valueOf(),
|
|
|
+ endData: dayjs(defineDate.value[1]).valueOf()
|
|
|
+ }
|
|
|
+ : { dateType: bulletinPrompt.date }),
|
|
|
+ queryType: bulletinPrompt.permission
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
+watchEffect(() => {
|
|
|
+ queryStage({
|
|
|
+ ...(stagePrompt.date === 'defineDate'
|
|
|
+ ? {
|
|
|
+ startDate: dayjs(defineDate.value[0]).valueOf(),
|
|
|
+ endData: dayjs(defineDate.value[1]).valueOf()
|
|
|
+ }
|
|
|
+ : { dateType: stagePrompt.date }),
|
|
|
+ queryType: stagePrompt.permission
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
+watchEffect(() => {
|
|
|
+ querySummary({
|
|
|
+ ...(summaryPrompt.date === 'defineDate'
|
|
|
+ ? {
|
|
|
+ startDate: dayjs(defineDate.value[0]).valueOf(),
|
|
|
+ endData: dayjs(defineDate.value[1]).valueOf()
|
|
|
+ }
|
|
|
+ : { dateType: summaryPrompt.date }),
|
|
|
+ queryType: summaryPrompt.permission
|
|
|
+ });
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
@@ -34,25 +146,98 @@ const option: EChartsOption = {
|
|
|
<section class="flex-[4]">
|
|
|
<div class="flex gap-3 mb-4">
|
|
|
<div class="w-40">
|
|
|
- <el-select size="small"></el-select>
|
|
|
+ <el-select
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ :model-value="bulletinPrompt.permission"
|
|
|
+ @change="(value) => (bulletinPrompt.permission = value)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="permission in permissionOptions"
|
|
|
+ :label="permission.label"
|
|
|
+ :value="permission.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
</div>
|
|
|
<div class="w-40">
|
|
|
- <el-select size="small"></el-select>
|
|
|
+ <el-select
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ :model-value="bulletinPrompt.date"
|
|
|
+ @change="(value) => (bulletinPrompt.date = value)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="date in dateOptions"
|
|
|
+ :label="date.label"
|
|
|
+ :value="date.value"
|
|
|
+ />
|
|
|
+ <el-option v-if="defineDate" label="自定义" value="defineDate" />
|
|
|
+ </el-select>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="border-gray-200 border rounded p-3">
|
|
|
<div class="flex gap-1.5 items-center mb-3">
|
|
|
+ <img width="16" src="../../assets/trend.png" />
|
|
|
<div class="text-sm font-medium">销售简报</div>
|
|
|
<el-icon><QuestionFilled class="text-gray-500 text-sm" /></el-icon>
|
|
|
</div>
|
|
|
<div class="grid xl:grid-cols-4 lg:grid-cols-3 grid-cols-2 gap-4">
|
|
|
- <TrendCard title="新增客户" :number="4" unit="人" />
|
|
|
- <TrendCard title="新增联系人" :number="4" unit="人" />
|
|
|
- <TrendCard title="新增商机" :number="4" unit="个" />
|
|
|
- <TrendCard title="新增销售订单" :number="4" unit="个" />
|
|
|
- <TrendCard title="销售订单金额" :number="4" unit="元" />
|
|
|
- <TrendCard title="商机金额" :number="4" unit="元" />
|
|
|
- <TrendCard title="新增线索" :number="4" unit="个" />
|
|
|
+ <TrendCard
|
|
|
+ title="新增客户"
|
|
|
+ unit="人"
|
|
|
+ :number="requestData?.bulletin?.custom.customCount"
|
|
|
+ :compare="requestData?.bulletin?.custom.customPromote"
|
|
|
+ />
|
|
|
+ <TrendCard
|
|
|
+ title="新增联系人"
|
|
|
+ unit="人"
|
|
|
+ :number="requestData?.bulletin?.contacts.contactsCount"
|
|
|
+ :compare="requestData?.bulletin?.contacts.contactsPromote"
|
|
|
+ />
|
|
|
+ <TrendCard
|
|
|
+ title="新增商机"
|
|
|
+ unit="个"
|
|
|
+ :number="
|
|
|
+ requestData?.bulletin?.businessOpportunity
|
|
|
+ .businessOpportunityCount
|
|
|
+ "
|
|
|
+ :compare="
|
|
|
+ requestData?.bulletin?.businessOpportunity
|
|
|
+ .businessOpportunityPromote
|
|
|
+ "
|
|
|
+ />
|
|
|
+ <TrendCard
|
|
|
+ title="新增销售订单"
|
|
|
+ unit="个"
|
|
|
+ :number="requestData?.bulletin?.salesOrder.salesOrderCount"
|
|
|
+ :compare="requestData?.bulletin?.salesOrder.salesOrderPromote"
|
|
|
+ />
|
|
|
+ <TrendCard
|
|
|
+ title="销售订单金额"
|
|
|
+ unit="元"
|
|
|
+ :number="requestData?.bulletin?.salesOrdersPrice.salesOrdersPrice"
|
|
|
+ :compare="
|
|
|
+ requestData?.bulletin?.salesOrdersPrice.salesOrderPricePromote
|
|
|
+ "
|
|
|
+ />
|
|
|
+ <TrendCard
|
|
|
+ title="商机金额"
|
|
|
+ unit="元"
|
|
|
+ :number="
|
|
|
+ requestData?.bulletin?.businessOpportunityPrice
|
|
|
+ .businessOpportunityPrice
|
|
|
+ "
|
|
|
+ :compare="
|
|
|
+ requestData?.bulletin?.businessOpportunityPrice
|
|
|
+ .businessOpportunityPromote
|
|
|
+ "
|
|
|
+ />
|
|
|
+ <TrendCard
|
|
|
+ title="新增线索"
|
|
|
+ unit="个"
|
|
|
+ :number="requestData?.bulletin?.clue.clueCount"
|
|
|
+ :compare="requestData?.bulletin?.clue.cluePromote"
|
|
|
+ />
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="my-8 flex gap-4 items-start">
|
|
@@ -60,67 +245,158 @@ const option: EChartsOption = {
|
|
|
<div class="text-sm font-medium">数据汇总</div>
|
|
|
<div class="flex gap-3 mb-8 mt-2">
|
|
|
<div class="w-40">
|
|
|
- <el-select size="small"></el-select>
|
|
|
+ <el-select
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ :model-value="summaryPrompt.permission"
|
|
|
+ @change="(value) => (summaryPrompt.permission = value)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="permission in permissionOptions"
|
|
|
+ :label="permission.label"
|
|
|
+ :value="permission.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
</div>
|
|
|
<div class="w-40">
|
|
|
- <el-select size="small"></el-select>
|
|
|
+ <el-select
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ :model-value="summaryPrompt.date"
|
|
|
+ @change="(value) => (summaryPrompt.date = value)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="date in dateOptions"
|
|
|
+ :label="date.label"
|
|
|
+ :value="date.value"
|
|
|
+ />
|
|
|
+ <el-option
|
|
|
+ v-if="defineDate"
|
|
|
+ label="自定义"
|
|
|
+ value="defineDate"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
</div>
|
|
|
</div>
|
|
|
<Divider title="客户汇总" />
|
|
|
<div class="my-6 grid grid-cols-4 gap-2">
|
|
|
- <SimpleCard />
|
|
|
- <SimpleCard />
|
|
|
- <SimpleCard />
|
|
|
- <SimpleCard />
|
|
|
+ <SimpleCard
|
|
|
+ title="新增客户"
|
|
|
+ unit="个"
|
|
|
+ :number="requestData.summary?.customDataSummary.newNum"
|
|
|
+ />
|
|
|
+ <SimpleCard
|
|
|
+ title="转成交客户"
|
|
|
+ unit="个"
|
|
|
+ :number="requestData.summary?.customDataSummary.closeDealNum"
|
|
|
+ />
|
|
|
</div>
|
|
|
<Divider title="商机汇总" />
|
|
|
<div class="my-6 grid grid-cols-4 gap-2">
|
|
|
- <SimpleCard />
|
|
|
- <SimpleCard />
|
|
|
- <SimpleCard />
|
|
|
- <SimpleCard />
|
|
|
+ <SimpleCard
|
|
|
+ title="新增商机"
|
|
|
+ unit="个"
|
|
|
+ :number="
|
|
|
+ requestData.summary?.businessOpportunityDataSummary.newNum
|
|
|
+ "
|
|
|
+ />
|
|
|
+ <SimpleCard
|
|
|
+ title="赢单商机"
|
|
|
+ unit="个"
|
|
|
+ :number="
|
|
|
+ requestData.summary?.businessOpportunityDataSummary.winning
|
|
|
+ "
|
|
|
+ />
|
|
|
+ <SimpleCard
|
|
|
+ title="输单商机"
|
|
|
+ unit="个"
|
|
|
+ :number="
|
|
|
+ requestData.summary?.businessOpportunityDataSummary.losting
|
|
|
+ "
|
|
|
+ />
|
|
|
+ <SimpleCard
|
|
|
+ title="商机总金额"
|
|
|
+ unit="元"
|
|
|
+ :number="
|
|
|
+ requestData.summary?.businessOpportunityDataSummary
|
|
|
+ .allAmountOfMoney
|
|
|
+ "
|
|
|
+ />
|
|
|
</div>
|
|
|
<Divider title="线索汇总" />
|
|
|
<div class="my-6 grid grid-cols-4 gap-2">
|
|
|
- <SimpleCard />
|
|
|
- <SimpleCard />
|
|
|
- <SimpleCard />
|
|
|
- <SimpleCard />
|
|
|
+ <SimpleCard
|
|
|
+ title="新增线索"
|
|
|
+ unit="个"
|
|
|
+ :number="requestData.summary?.clueDataSummary.newNum"
|
|
|
+ />
|
|
|
+ <SimpleCard
|
|
|
+ title="线索转商机"
|
|
|
+ unit="个"
|
|
|
+ :number="requestData.summary?.clueDataSummary.changeNum"
|
|
|
+ />
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="border-gray-200 border rounded p-3 flex-1">
|
|
|
<div class="text-sm font-medium">商机阶段</div>
|
|
|
<div class="flex gap-3 mb-8 mt-2">
|
|
|
<div class="w-40">
|
|
|
- <el-select size="small"></el-select>
|
|
|
+ <el-select
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ :model-value="stagePrompt.permission"
|
|
|
+ @change="(value) => (stagePrompt.permission = value)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="permission in permissionOptions"
|
|
|
+ :label="permission.label"
|
|
|
+ :value="permission.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
</div>
|
|
|
<div class="w-40">
|
|
|
- <el-select size="small"></el-select>
|
|
|
+ <el-select
|
|
|
+ clearable
|
|
|
+ size="small"
|
|
|
+ :model-value="stagePrompt.date"
|
|
|
+ @change="(value) => (stagePrompt.date = value)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="date in dateOptions"
|
|
|
+ :label="date.label"
|
|
|
+ :value="date.value"
|
|
|
+ />
|
|
|
+ <el-option
|
|
|
+ v-if="defineDate"
|
|
|
+ label="自定义"
|
|
|
+ value="defineDate"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="h-60">
|
|
|
- <Echarts :option="option"></Echarts>
|
|
|
+ <Echarts :option="chartOptions"></Echarts>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</section>
|
|
|
- <nav class="flex-1 min-w-60 sticky right-0 top-9">
|
|
|
+ <nav class="flex-1 min-w-60 sticky right-0 top-9 max-lg:hidden">
|
|
|
<div class="border border-gray-200 rounded w-3/4 text-sm text-gray-500">
|
|
|
- <div class="p-2 bg-sky-100 border-l-2 border-blue-700">仅本人</div>
|
|
|
- <div class="p-2">本人及下属</div>
|
|
|
- <div class="p-2">仅本部门</div>
|
|
|
- <div class="p-2">本部门及下属</div>
|
|
|
+ <div class="p-2" v-for="primission in permissionOptions">
|
|
|
+ {{ primission.label }}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div class="border border-gray-200 rounded text-sm text-gray-500 mt-4">
|
|
|
- <div class="p-2 bg-sky-100 border-l-2 border-blue-700">本月</div>
|
|
|
- <div class="p-2">本周</div>
|
|
|
- <div class="p-2">本年</div>
|
|
|
+ <div class="p-2" v-for="date in dateOptions">{{ date.label }}</div>
|
|
|
<div class="p-2">
|
|
|
<div>自定义</div>
|
|
|
<el-date-picker
|
|
|
type="daterange"
|
|
|
class="max-w-full mt-2"
|
|
|
- ></el-date-picker>
|
|
|
+ v-model="defineDate"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ />
|
|
|
</div>
|
|
|
</div>
|
|
|
</nav>
|