Commit 96128491e1583ad61e5d91c089a0b7c71f86d6a6

Authored by ww
1 parent cc8a9caa

perf: 优化首页统计图表

@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 watch( 22 watch(
23 () => props.customerList, 23 () => props.customerList,
24 (newValue) => { 24 (newValue) => {
25 - const transferResult = newValue.map((item) => [item.ts, item.value]); 25 + const transferResult = newValue.map((item) => [item.date, item.value]);
26 26
27 setOptions({ 27 setOptions({
28 tooltip: { 28 tooltip: {
@@ -35,7 +35,7 @@ @@ -35,7 +35,7 @@
35 }, 35 },
36 }, 36 },
37 xAxis: { 37 xAxis: {
38 - type: 'time', 38 + type: 'category',
39 splitLine: { 39 splitLine: {
40 show: true, 40 show: true,
41 lineStyle: { 41 lineStyle: {
@@ -90,7 +90,7 @@ @@ -90,7 +90,7 @@
90 trend: props.type, 90 trend: props.type,
91 }); 91 });
92 92
93 - const transferResult = res.map((item) => [item.ts, item.value]); 93 + const transferResult = res.map((item) => [item.date, item.value]);
94 setOptions({ 94 setOptions({
95 tooltip: { 95 tooltip: {
96 trigger: 'axis', 96 trigger: 'axis',
@@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
31 }, 31 },
32 }, 32 },
33 xAxis: { 33 xAxis: {
34 - type: 'time', 34 + type: 'category',
35 splitLine: { 35 splitLine: {
36 show: true, 36 show: true,
37 lineStyle: { 37 lineStyle: {
@@ -79,11 +79,11 @@ @@ -79,11 +79,11 @@
79 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); 79 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
80 onMounted(async () => { 80 onMounted(async () => {
81 const res = await getTrendData({ 81 const res = await getTrendData({
82 - ...getDateByShortcutQueryKey(ShortcutQueryKeyEnum.LATEST_30_DAY), 82 + ...getDateByShortcutQueryKey(ShortcutQueryKeyEnum.LATEST_1_MONTH),
83 trend: 'CUSTOMER_TREND', 83 trend: 'CUSTOMER_TREND',
84 }); 84 });
85 85
86 - const transferResult = res.map((item) => [item.ts, item.value]); 86 + const transferResult = res.map((item) => [item.date, item.value]);
87 setOptions({ 87 setOptions({
88 tooltip: { 88 tooltip: {
89 trigger: 'axis', 89 trigger: 'axis',
@@ -95,7 +95,7 @@ @@ -95,7 +95,7 @@
95 }, 95 },
96 }, 96 },
97 xAxis: { 97 xAxis: {
98 - type: 'time', 98 + type: 'category',
99 splitLine: { 99 splitLine: {
100 show: true, 100 show: true,
101 lineStyle: { 101 lineStyle: {
@@ -37,7 +37,15 @@ @@ -37,7 +37,15 @@
37 <DatePicker 37 <DatePicker
38 @change="(_, DateString) => onDateChange(_, DateString, role === RoleEnum.CUSTOMER_USER)" 38 @change="(_, DateString) => onDateChange(_, DateString, role === RoleEnum.CUSTOMER_USER)"
39 v-model:value="dateValue" 39 v-model:value="dateValue"
40 - /> 40 + >
  41 + <Button
  42 + type="link"
  43 + class="!px-0"
  44 + :style="dateValue ? { color: '#0960bd', fontWeight: 500 } : { color: '#000000d9' }"
  45 + >
  46 + {{ dateValue ? (dateValue as moment.Moment).format('YYYY-MM-DD') : '自定义' }}
  47 + </Button>
  48 + </DatePicker>
41 </div> 49 </div>
42 </template> 50 </template>
43 <div v-if="activeKey === '1'"> 51 <div v-if="activeKey === '1'">
@@ -99,13 +107,13 @@ @@ -99,13 +107,13 @@
99 <Tooltip :overlayStyle="{ maxWidth: '340px' }"> 107 <Tooltip :overlayStyle="{ maxWidth: '340px' }">
100 <template #title> 108 <template #title>
101 <section> 109 <section>
102 - <div>30天: 查询最近30天的数据,间隔时间为1天.</div> 110 + <div>最近一个月: 查询最近一个月的数据,间隔时间为1天.</div>
103 <div>最近三个月: 查询最近三个月的数据,间隔时间为1天.</div> 111 <div>最近三个月: 查询最近三个月的数据,间隔时间为1天.</div>
104 - <div>最近一年: 查询最近一年的数据,间隔时间为30天.</div> 112 + <div>最近一年: 查询最近一年的数据,间隔时间为1月.</div>
105 <div> 113 <div>
106 间隔时间: 114 间隔时间:
107 <span class="font-bold underline"> 以当天的(最后时间)作为结束时间 </span> 115 <span class="font-bold underline"> 以当天的(最后时间)作为结束时间 </span>
108 - ,往前推移对应天数或小时的时间作为开始时间,然后在此时间区间内进行分组聚合查询. 116 + ,往前推移对应天数或的时间作为开始时间,然后在此时间区间内进行分组聚合查询.
109 </div> 117 </div>
110 </section> 118 </section>
111 </template> 119 </template>
@@ -120,9 +128,28 @@ @@ -120,9 +128,28 @@
120 </template> 128 </template>
121 <DatePicker.RangePicker 129 <DatePicker.RangePicker
122 @change="onDateCustomerChange" 130 @change="onDateCustomerChange"
  131 + :disabledDate="handleDisableDate"
  132 + @calendarChange="handleCalendarChange"
123 size="small" 133 size="small"
124 v-model:value="customerDateValue" 134 v-model:value="customerDateValue"
125 - /> 135 + >
  136 + <Button
  137 + type="link"
  138 + class="!px-0"
  139 + :style="
  140 + customerDateValue && customerDateValue.length
  141 + ? { color: '#0960bd', fontWeight: 500 }
  142 + : { color: '#000000d9' }
  143 + "
  144 + >{{
  145 + customerDateValue && customerDateValue.length
  146 + ? `${(customerDateValue?.[0] as moment.Moment)?.format('YYYY-MM-DD')}
  147 + ~
  148 + ${(customerDateValue?.[1] as moment.Moment)?.format('YYYY-MM-DD')}`
  149 + : '自定义'
  150 + }}</Button
  151 + >
  152 + </DatePicker.RangePicker>
126 </div> 153 </div>
127 </template> 154 </template>
128 <CustomerTrend :customerTrendList="customerTrendList" /> 155 <CustomerTrend :customerTrendList="customerTrendList" />
@@ -130,8 +157,8 @@ @@ -130,8 +157,8 @@
130 </div> 157 </div>
131 </template> 158 </template>
132 <script lang="ts" setup> 159 <script lang="ts" setup>
133 - import { ref, reactive } from 'vue';  
134 - import { Card, DatePicker, Tooltip } from 'ant-design-vue'; 160 + import { ref, reactive, unref } from 'vue';
  161 + import { Card, DatePicker, Tooltip, Button } from 'ant-design-vue';
135 import VisitAnalysis from './VisitAnalysis.vue'; 162 import VisitAnalysis from './VisitAnalysis.vue';
136 import VisitAnalysisBar from './VisitAnalysisBar.vue'; 163 import VisitAnalysisBar from './VisitAnalysisBar.vue';
137 import { RoleEnum, isAdmin } from '/@/enums/roleEnum'; 164 import { RoleEnum, isAdmin } from '/@/enums/roleEnum';
@@ -146,6 +173,7 @@ @@ -146,6 +173,7 @@
146 import { getTrendData } from '/@/api/dashboard'; 173 import { getTrendData } from '/@/api/dashboard';
147 import { useGlobSetting } from '/@/hooks/setting'; 174 import { useGlobSetting } from '/@/hooks/setting';
148 import { QuestionCircleOutlined } from '@ant-design/icons-vue'; 175 import { QuestionCircleOutlined } from '@ant-design/icons-vue';
  176 + import { RangePickerValue } from 'ant-design-vue/lib/date-picker/interface';
149 177
150 defineExpose({ 178 defineExpose({
151 isAdmin, 179 isAdmin,
@@ -496,6 +524,18 @@ @@ -496,6 +524,18 @@
496 // onDateTenantChange, 524 // onDateTenantChange,
497 onDateCustomerChange, 525 onDateCustomerChange,
498 } = useDate(); 526 } = useDate();
  527 +
  528 + const handleCalendarChange = (val: RangePickerValue) => {
  529 + customerDateValue.value = val as any;
  530 + };
  531 +
  532 + const handleDisableDate = (current: moment.Moment) => {
  533 + if (!unref(customerDateValue) || unref(customerDateValue).length === 0) {
  534 + return false;
  535 + }
  536 + const diffDate = current.diff(unref(customerDateValue)[0], 'days');
  537 + return Math.abs(diffDate) > 30;
  538 + };
499 </script> 539 </script>
500 540
501 <style lang="less"> 541 <style lang="less">
@@ -47,7 +47,15 @@ @@ -47,7 +47,15 @@
47 <DatePicker 47 <DatePicker
48 @change="(_, DateString) => onDateChange(_, DateString, role === RoleEnum.CUSTOMER_USER)" 48 @change="(_, DateString) => onDateChange(_, DateString, role === RoleEnum.CUSTOMER_USER)"
49 v-model:value="dateValue" 49 v-model:value="dateValue"
50 - /> 50 + >
  51 + <Button
  52 + type="link"
  53 + class="!px-0"
  54 + :style="dateValue ? { color: '#0960bd', fontWeight: 500 } : { color: '#000000d9' }"
  55 + >
  56 + {{ dateValue ? (dateValue as moment.Moment).format('YYYY-MM-DD') : '自定义' }}
  57 + </Button>
  58 + </DatePicker>
51 </div> 59 </div>
52 </template> 60 </template>
53 <!-- <div v-if="activeKey === '1'"> 61 <!-- <div v-if="activeKey === '1'">
@@ -84,13 +92,13 @@ @@ -84,13 +92,13 @@
84 <Tooltip :overlayStyle="{ maxWidth: '340px' }"> 92 <Tooltip :overlayStyle="{ maxWidth: '340px' }">
85 <template #title> 93 <template #title>
86 <section> 94 <section>
87 - <div>30天: 查询最近30天的数据,间隔时间为1天.</div> 95 + <div>最近一个月: 查询最近一个月的数据,间隔时间为1天.</div>
88 <div>最近三个月: 查询最近三个月的数据,间隔时间为1天.</div> 96 <div>最近三个月: 查询最近三个月的数据,间隔时间为1天.</div>
89 - <div>最近一年: 查询最近一年的数据,间隔时间为30天.</div> 97 + <div>最近一年: 查询最近一年的数据,间隔时间为1月.</div>
90 <div> 98 <div>
91 间隔时间: 99 间隔时间:
92 <span class="font-bold underline"> 以当天的(最后时间)作为结束时间 </span> 100 <span class="font-bold underline"> 以当天的(最后时间)作为结束时间 </span>
93 - ,往前推移对应天数或小时的时间作为开始时间,然后在此时间区间内进行分组聚合查询. 101 + ,往前推移对应天数或的时间作为开始时间,然后在此时间区间内进行分组聚合查询.
94 </div> 102 </div>
95 </section> 103 </section>
96 </template> 104 </template>
@@ -106,8 +114,27 @@ @@ -106,8 +114,27 @@
106 <DatePicker.RangePicker 114 <DatePicker.RangePicker
107 @change="onDateTenantChange" 115 @change="onDateTenantChange"
108 size="small" 116 size="small"
  117 + @calendarChange="handleCalendarChange"
  118 + :disabledDate="handleDisableDate"
109 v-model:value="tenantDateValue" 119 v-model:value="tenantDateValue"
110 - /> 120 + >
  121 + <Button
  122 + type="link"
  123 + class="!px-0"
  124 + :style="
  125 + tenantDateValue && tenantDateValue.length
  126 + ? { color: '#0960bd', fontWeight: 500 }
  127 + : { color: '#000000d9' }
  128 + "
  129 + >{{
  130 + tenantDateValue && tenantDateValue.length
  131 + ? `${(tenantDateValue?.[0] as moment.Moment)?.format('YYYY-MM-DD')}
  132 + ~
  133 + ${(tenantDateValue?.[1] as moment.Moment)?.format('YYYY-MM-DD')}`
  134 + : '自定义'
  135 + }}</Button
  136 + >
  137 + </DatePicker.RangePicker>
111 </div> 138 </div>
112 </template> 139 </template>
113 <TenantTrend :tenantTrendList="tenantTrendList" /> 140 <TenantTrend :tenantTrendList="tenantTrendList" />
@@ -139,8 +166,8 @@ @@ -139,8 +166,8 @@
139 </div> 166 </div>
140 </template> 167 </template>
141 <script lang="ts" setup> 168 <script lang="ts" setup>
142 - import { ref, reactive } from 'vue';  
143 - import { Card, DatePicker, Tooltip } from 'ant-design-vue'; 169 + import { ref, reactive, unref } from 'vue';
  170 + import { Card, DatePicker, Tooltip, Button } from 'ant-design-vue';
144 import { QuestionCircleOutlined } from '@ant-design/icons-vue'; 171 import { QuestionCircleOutlined } from '@ant-design/icons-vue';
145 // import VisitAnalysis from './VisitAnalysis.vue'; 172 // import VisitAnalysis from './VisitAnalysis.vue';
146 import VisitAnalysisBar from './VisitAnalysisBar.vue'; 173 import VisitAnalysisBar from './VisitAnalysisBar.vue';
@@ -155,6 +182,7 @@ @@ -155,6 +182,7 @@
155 import { useDate } from '../hooks/useDate'; 182 import { useDate } from '../hooks/useDate';
156 import { getTrendData } from '/@/api/dashboard'; 183 import { getTrendData } from '/@/api/dashboard';
157 import { useGlobSetting } from '/@/hooks/setting'; 184 import { useGlobSetting } from '/@/hooks/setting';
  185 + import { RangePickerValue } from 'ant-design-vue/lib/date-picker/interface';
158 186
159 defineExpose({ 187 defineExpose({
160 isAdmin, 188 isAdmin,
@@ -514,6 +542,18 @@ @@ -514,6 +542,18 @@
514 onDateTenantChange, 542 onDateTenantChange,
515 // onDateCustomerChange, 543 // onDateCustomerChange,
516 } = useDate(); 544 } = useDate();
  545 +
  546 + const handleCalendarChange = (val: RangePickerValue) => {
  547 + tenantDateValue.value = val as any;
  548 + };
  549 +
  550 + const handleDisableDate = (current: moment.Moment) => {
  551 + if (!unref(tenantDateValue) || unref(tenantDateValue).length === 0) {
  552 + return false;
  553 + }
  554 + const diffDate = current.diff(unref(tenantDateValue)[0], 'days');
  555 + return Math.abs(diffDate) > 30;
  556 + };
517 </script> 557 </script>
518 558
519 <style lang="less"> 559 <style lang="less">
@@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
31 }, 31 },
32 }, 32 },
33 xAxis: { 33 xAxis: {
34 - type: 'time', 34 + type: 'category',
35 splitLine: { 35 splitLine: {
36 show: true, 36 show: true,
37 lineStyle: { 37 lineStyle: {
@@ -79,10 +79,10 @@ @@ -79,10 +79,10 @@
79 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); 79 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
80 onMounted(async () => { 80 onMounted(async () => {
81 const res = await getTrendData({ 81 const res = await getTrendData({
82 - ...getDateByShortcutQueryKey(ShortcutQueryKeyEnum.LATEST_30_DAY), 82 + ...getDateByShortcutQueryKey(ShortcutQueryKeyEnum.LATEST_1_MONTH),
83 trend: 'TENANT_TREND', 83 trend: 'TENANT_TREND',
84 }); 84 });
85 - const transferResult = res.map((item) => [item.ts, item.value]); 85 + const transferResult = res.map((item) => [item.date, item.value]);
86 setOptions({ 86 setOptions({
87 tooltip: { 87 tooltip: {
88 trigger: 'axis', 88 trigger: 'axis',
@@ -94,7 +94,7 @@ @@ -94,7 +94,7 @@
94 }, 94 },
95 }, 95 },
96 xAxis: { 96 xAxis: {
97 - type: 'time', 97 + type: 'category',
98 splitLine: { 98 splitLine: {
99 show: true, 99 show: true,
100 lineStyle: { 100 lineStyle: {
1 import { dateUtil, formatToDateTime } from '/@/utils/dateUtil'; 1 import { dateUtil, formatToDateTime } from '/@/utils/dateUtil';
2 import { ref } from 'vue'; 2 import { ref } from 'vue';
3 import { getTrendData } from '/@/api/dashboard'; 3 import { getTrendData } from '/@/api/dashboard';
  4 +import { RangePickerValue } from 'ant-design-vue/lib/date-picker/interface';
4 5
5 export enum ShortcutQueryKeyEnum { 6 export enum ShortcutQueryKeyEnum {
6 - LATEST_30_DAY = 'LATEST_30_DAY', 7 + LATEST_1_MONTH = 'LATEST_1_MONTH',
7 LATEST_3_MONTH = 'LATEST_3_MONTH', 8 LATEST_3_MONTH = 'LATEST_3_MONTH',
8 LATEST_1_YEAR = 'LATEST_1_YEAR', 9 LATEST_1_YEAR = 'LATEST_1_YEAR',
9 } 10 }
10 11
11 export function getDateByShortcutQueryKey(value: ShortcutQueryKeyEnum) { 12 export function getDateByShortcutQueryKey(value: ShortcutQueryKeyEnum) {
12 const mapping = { 13 const mapping = {
13 - [ShortcutQueryKeyEnum.LATEST_30_DAY]: () => { 14 + [ShortcutQueryKeyEnum.LATEST_1_MONTH]: () => {
14 return { 15 return {
15 - startTs: dateUtil().subtract(30, 'day').startOf('day').valueOf(), 16 + startTs: dateUtil().subtract(1, 'month').startOf('day').valueOf(),
16 interval: 24 * 60 * 60 * 1000, 17 interval: 24 * 60 * 60 * 1000,
17 }; 18 };
18 }, 19 },
@@ -40,13 +41,13 @@ export function getDateByShortcutQueryKey(value: ShortcutQueryKeyEnum) { @@ -40,13 +41,13 @@ export function getDateByShortcutQueryKey(value: ShortcutQueryKeyEnum) {
40 41
41 export function useDate() { 42 export function useDate() {
42 const tenantDateValue = ref([]); 43 const tenantDateValue = ref([]);
43 - const customerDateValue = ref([]); 44 + const customerDateValue = ref<RangePickerValue>([]);
44 const tenantTrendList = ref([]); 45 const tenantTrendList = ref([]);
45 const customerTrendList = ref([]); 46 const customerTrendList = ref([]);
46 const activeTenantIndex = ref(0); 47 const activeTenantIndex = ref(0);
47 const activeCustomerIndex = ref(0); 48 const activeCustomerIndex = ref(0);
48 const TenantOrCustomerDateList = ref([ 49 const TenantOrCustomerDateList = ref([
49 - { label: '30天', value: ShortcutQueryKeyEnum.LATEST_30_DAY }, 50 + { label: '最近一个月', value: ShortcutQueryKeyEnum.LATEST_1_MONTH },
50 { label: '最近三个月', value: ShortcutQueryKeyEnum.LATEST_3_MONTH }, 51 { label: '最近三个月', value: ShortcutQueryKeyEnum.LATEST_3_MONTH },
51 { label: '最近一年', value: ShortcutQueryKeyEnum.LATEST_1_YEAR }, 52 { label: '最近一年', value: ShortcutQueryKeyEnum.LATEST_1_YEAR },
52 ]); 53 ]);
@@ -65,7 +66,7 @@ export function useDate() { @@ -65,7 +66,7 @@ export function useDate() {
65 ...getDateByShortcutQueryKey(value), 66 ...getDateByShortcutQueryKey(value),
66 trend: 'TENANT_TREND', 67 trend: 'TENANT_TREND',
67 }); 68 });
68 - tenantTrendList.value = res.map((item) => [item.ts, item.value]); 69 + tenantTrendList.value = res.map((item) => [item.date, item.value]);
69 } else { 70 } else {
70 if (activeCustomerIndex.value === index) return; 71 if (activeCustomerIndex.value === index) return;
71 activeCustomerIndex.value = index; 72 activeCustomerIndex.value = index;
@@ -74,7 +75,7 @@ export function useDate() { @@ -74,7 +75,7 @@ export function useDate() {
74 ...getDateByShortcutQueryKey(value), 75 ...getDateByShortcutQueryKey(value),
75 trend: 'CUSTOMER_TREND', 76 trend: 'CUSTOMER_TREND',
76 }); 77 });
77 - customerTrendList.value = res.map((item) => [item.ts, item.value]); 78 + customerTrendList.value = res.map((item) => [item.date, item.value]);
78 } 79 }
79 } 80 }
80 81