| | |
| | | series: [getPieSeries(seriesName, data)], |
| | | }); |
| | | |
| | | /** |
| | | * 中国地图:ECharts 默认只把地图撑到容器高度的 80%,容器加宽并不会让地图变大。 |
| | | * 用 layoutCenter + layoutSize 把地图顶到 92%,并稍微下移给标题留位置。 |
| | | */ |
| | | const getMapSeries = (name: string, data: any[]) => ({ |
| | | name, |
| | | type: 'map' as const, |
| | | map: 'china', |
| | | roam: false, |
| | | selectedMode: false, |
| | | layoutCenter: ['50%', '52%'], |
| | | layoutSize: '92%', |
| | | data, |
| | | }); |
| | | |
| | | export function getChartOptions(activeTabName: any, res: any): any { |
| | | switch (activeTabName) { |
| | | case 'area': { |
| | |
| | | max: leftMax, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '客户地域分布', |
| | | type: 'map', |
| | | map: 'china', |
| | | roam: false, |
| | | selectedMode: false, |
| | | data: data.map((item: any) => { |
| | | getMapSeries( |
| | | '客户地域分布', |
| | | data.map((item: any) => { |
| | | return { |
| | | name: item.areaName, |
| | | value: item.customerCount || 0, |
| | | }; |
| | | }), |
| | | }, |
| | | ), |
| | | ], |
| | | }, |
| | | right: { |
| | |
| | | max: rightMax, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '客户地域分布', |
| | | type: 'map', |
| | | map: 'china', |
| | | roam: false, |
| | | selectedMode: false, |
| | | data: data.map((item: any) => { |
| | | getMapSeries( |
| | | '客户地域分布', |
| | | data.map((item: any) => { |
| | | return { |
| | | name: item.areaName, |
| | | value: item.dealCount || 0, |
| | | }; |
| | | }), |
| | | }, |
| | | ), |
| | | ], |
| | | }, |
| | | }; |
| | |
| | | import { useUserStore } from '@vben/stores'; |
| | | import { beginOfDay, endOfDay, formatDateTime, handleTree } from '@vben/utils'; |
| | | |
| | | import dayjs from 'dayjs'; |
| | | |
| | | import { getSimpleDeptList } from '#/api/system/dept'; |
| | | import { getSimpleUserList } from '#/api/system/user'; |
| | | import { getRangePickerDefaultProps } from '#/utils'; |
| | |
| | | format: 'YYYY-MM-DD', |
| | | }, |
| | | defaultValue: [ |
| | | formatDateTime(beginOfDay(new Date(Date.now() - 3600 * 1000 * 24 * 7))), |
| | | formatDateTime(endOfDay(new Date(Date.now() - 3600 * 1000 * 24))), |
| | | formatDateTime(beginOfDay(dayjs().subtract(2, 'month').toDate())), |
| | | formatDateTime(endOfDay(new Date())), |
| | | ], |
| | | }, |
| | | { |
| | |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { CrmStatisticsCustomerApi } from '#/api/crm/statistics/customer'; |
| | | |
| | | import { onMounted, ref } from 'vue'; |
| | | import { computed, onMounted, ref } from 'vue'; |
| | | |
| | | import { ContentWrap, Page } from '@vben/common-ui'; |
| | | import { EchartsUI, useEcharts } from '@vben/plugins/echarts'; |
| | |
| | | const rightChartRef = ref<EchartsUIType>(); |
| | | const { renderEcharts: renderLeftEcharts } = useEcharts(leftChartRef); |
| | | const { renderEcharts: renderRightEcharts } = useEcharts(rightChartRef); |
| | | |
| | | /** |
| | | * 城市分布分析:两张地图各占一整行。 |
| | | * 地图图形的大小由容器高度决定(ECharts 按短边自适应,加宽只多留白), |
| | | * 所以这里把高度给足,配合 chartOptions 里的 layoutSize 撑满。 |
| | | */ |
| | | const isAreaTab = computed(() => activeTabName.value === 'area'); |
| | | const chartHeight = computed(() => (isAreaTab.value ? '700px' : '300px')); |
| | | |
| | | const [QueryForm, formApi] = useVbenForm({ |
| | | commonConfig: { |
| | |
| | | :force-render="true" |
| | | /> |
| | | </Tabs> |
| | | <div class="mt-5 flex"> |
| | | <EchartsUI class="m-4 w-1/2" ref="leftChartRef" /> |
| | | <EchartsUI class="m-4 w-1/2" ref="rightChartRef" /> |
| | | <div class="mt-5 flex" :class="{ 'flex-col': isAreaTab }"> |
| | | <EchartsUI |
| | | class="m-4" |
| | | :class="isAreaTab ? 'w-full' : 'w-1/2'" |
| | | :height="chartHeight" |
| | | ref="leftChartRef" |
| | | /> |
| | | <EchartsUI |
| | | class="m-4" |
| | | :class="isAreaTab ? 'w-full' : 'w-1/2'" |
| | | :height="chartHeight" |
| | | ref="rightChartRef" |
| | | /> |
| | | </div> |
| | | <Grid v-show="activeTabName !== 'area'" /> |
| | | </ContentWrap> |
| | |
| | | import { useUserStore } from '@vben/stores'; |
| | | import { beginOfDay, endOfDay, formatDateTime, handleTree } from '@vben/utils'; |
| | | |
| | | import dayjs from 'dayjs'; |
| | | |
| | | import { getSimpleDeptList } from '#/api/system/dept'; |
| | | import { getRangePickerDefaultProps } from '#/utils'; |
| | | |
| | |
| | | format: 'YYYY-MM-DD', |
| | | }, |
| | | defaultValue: [ |
| | | formatDateTime(beginOfDay(new Date(Date.now() - 3600 * 1000 * 24 * 7))), |
| | | formatDateTime(endOfDay(new Date(Date.now() - 3600 * 1000 * 24))), |
| | | formatDateTime(beginOfDay(dayjs().subtract(2, 'month').toDate())), |
| | | formatDateTime(endOfDay(new Date())), |
| | | ], |
| | | }, |
| | | { |
| | |
| | | import type { EchartsUIType } from '@vben/plugins/echarts'; |
| | | |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { CrmStatisticsCustomerApi } from '#/api/crm/statistics/customer'; |
| | | import type { CrmStatisticsRankApi } from '#/api/crm/statistics/rank'; |
| | | |
| | | import { onMounted, ref } from 'vue'; |
| | | |
| | |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { getDatas } from '#/api/crm/statistics/customer'; |
| | | import { getDatas } from '#/api/crm/statistics/rank'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { getChartOptions } from './chartOptions'; |
| | |
| | | pagerConfig: { |
| | | enabled: false, |
| | | }, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async (_, formValues) => { |
| | | const res = await getDatas(activeTabName.value, formValues); |
| | | await renderEcharts(getChartOptions(activeTabName.value, res)); |
| | | return res; |
| | | }, |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'id', |
| | | isHover: true, |
| | |
| | | toolbarConfig: { |
| | | enabled: false, |
| | | }, |
| | | } as VxeTableGridOptions<CrmStatisticsCustomerApi.CustomerSummaryByUserRespVO>, |
| | | } as VxeTableGridOptions<CrmStatisticsRankApi.RankRespVO>, |
| | | }); |
| | | |
| | | /** tab 切换 */ |