123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- <script lang="ts" setup>
- 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, use } from 'echarts';
- import { dayjs } from 'element-plus';
- import {
- getSummaryData,
- getBulletinData,
- BulletinData,
- getStageData,
- RequestProps,
- StageData,
- SummaryData
- } from './api';
- 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
- }
- ];
- type PromptType = {
- permission?: 0 | 1 | 2 | 3;
- date?: 0 | 1 | 2 | any;
- sliceDate: [Date, Date];
- };
- const select1 = ref<HTMLDivElement>();
- const select2 = ref<HTMLDivElement>();
- const select3 = ref<HTMLDivElement>();
- const bulletinPrompt = reactive<PromptType>({
- permission: 0,
- date: 0,
- sliceDate: [new Date(), new Date()]
- });
- const summaryPrompt = reactive<PromptType>({
- permission: 0,
- date: 0,
- sliceDate: [new Date(), new Date()]
- });
- const stagePrompt = reactive<PromptType>({
- permission: 0,
- date: 0,
- sliceDate: [new Date(), new Date()]
- });
- 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'
- },
- xAxis: {
- type: 'value'
- },
- series: [
- {
- barWidth: 20,
- 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 === ('ignore' as any)
- ? {
- startDate: dayjs(bulletinPrompt.sliceDate[0]).format('YYYY-MM-DD'),
- endDate: dayjs(bulletinPrompt.sliceDate[1]).format('YYYY-MM-DD')
- }
- : { dateType: bulletinPrompt.date }),
- queryType: bulletinPrompt.permission
- });
- });
- watchEffect(() => {
- queryStage({
- ...(stagePrompt.date === ('ignore' as any)
- ? {
- startDate: dayjs(stagePrompt.sliceDate[0]).format('YYYY-MM-DD'),
- endDate: dayjs(stagePrompt.sliceDate[1]).format('YYYY-MM-DD')
- }
- : { dateType: stagePrompt.date }),
- queryType: stagePrompt.permission
- });
- });
- watchEffect(() => {
- querySummary({
- ...(summaryPrompt.date === ('ignore' as any)
- ? {
- startDate: dayjs(summaryPrompt.sliceDate[0]).format('YYYY-MM-DD'),
- endDate: dayjs(summaryPrompt.sliceDate[1]).format('YYYY-MM-DD')
- }
- : { dateType: summaryPrompt.date }),
- queryType: summaryPrompt.permission
- });
- });
- watchEffect(() => {
- console.log(bulletinPrompt.date, '-----', bulletinPrompt.sliceDate, '88888888---watchEffect');
- });
- </script>
- <template>
- <div class="m-5 bg-white min-h-full p-4 rounded">
- <section>
- <div class="flex gap-3 mb-4">
- <div class="w-40">
- <el-select
- size="small"
- :model-value="bulletinPrompt.permission"
- @change="(value: any) => (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
- ref="select1"
- size="small"
- :model-value="bulletinPrompt.date"
- @change="(value: any) => (bulletinPrompt.date = value)"
- >
- <el-option v-for="date in dateOptions" :label="date.label" :value="date.value" />
- <el-option label="自定义" value="ignore" disabled>
- <div class="flex gap-2 w-80">
- <el-date-picker
- size="small"
- :clearable="false"
- type="daterange"
- class="w-12"
- v-model="bulletinPrompt.sliceDate"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- />
- <el-button
- size="small"
- type="primary"
- @click="
- () => {
- select1?.blur();
- bulletinPrompt.date = 'ignore';
- }
- "
- >确认</el-button
- >
- </div>
- </el-option>
- </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="新增客户"
- 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">
- <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
- clearable
- size="small"
- :model-value="summaryPrompt.permission"
- @change="(value: any) => (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
- ref="select2"
- clearable
- size="small"
- :model-value="summaryPrompt.date"
- @change="(value: any) => (summaryPrompt.date = value)"
- >
- <el-option v-for="date in dateOptions" :label="date.label" :value="date.value" />
- <el-option label="自定义" value="ignore" disabled>
- <div class="flex gap-2 w-80">
- <el-date-picker
- size="small"
- :clearable="false"
- type="daterange"
- class="w-12"
- v-model="summaryPrompt.sliceDate"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- />
- <el-button
- size="small"
- type="primary"
- @click="
- () => {
- select2?.blur();
- summaryPrompt.date = 'ignore';
- }
- "
- >确认</el-button
- >
- </div>
- </el-option>
- </el-select>
- </div>
- </div>
- <Divider title="客户汇总" />
- <div class="my-6 grid grid-cols-4 gap-2">
- <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
- 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
- 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
- clearable
- size="small"
- :model-value="stagePrompt.permission"
- @change="(value: any) => (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
- ref="select3"
- clearable
- size="small"
- :model-value="stagePrompt.date"
- @change="(value: any) => (stagePrompt.date = value)"
- >
- <el-option v-for="date in dateOptions" :label="date.label" :value="date.value" />
- <el-option label="自定义" value="ignore" disabled>
- <div class="flex gap-2 w-80">
- <el-date-picker
- size="small"
- :clearable="false"
- type="daterange"
- class="w-12"
- v-model="stagePrompt.sliceDate"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- />
- <el-button
- size="small"
- type="primary"
- @click="
- () => {
- select3?.blur();
- stagePrompt.date = 'ignore';
- }
- "
- >确认</el-button
- >
- </div>
- </el-option>
- </el-select>
- </div>
- </div>
- <div class="h-60">
- <Echarts :option="chartOptions"></Echarts>
- </div>
- </div>
- </div>
- </section>
- </div>
- </template>
|