以下代码是以一个echarts图表的demo来展示常用的一些类型定义及使用方式:
包含了以下几个方面:
- Omit和Pick
- interface和type
- 泛型T和extends继承
- 类型库中取特定属性的类型定义的写法
types.ts
/**
* OperationReportDTO
*/
export interface OperationReportDTO {
businessLineId?: number;
endDate?: string;
platform?: 'pc' | 'ios' | 'android';
selectType?: 1 | 2 | 3 | 4;
startDate?: string;
/**
* 时间维度 日1,周2,月3
*/
timeDimension?: 1 | 2 | 3;
}
EchartsDemo.tsx
import { Panel, Spin } from 'ant-design';
import { useRequest } from '@/hooks';
import { getImSessionData } from '@/services/operationManage/data';
import dayjs from 'dayjs';
import ReactEcharts from 'echarts-for-react';
import React, { useMemo } from 'react';
import { dateFormat1, getZoomConfig, gridConfig, lineConfig } from '../feature/constant';
import { FilterForm } from './FilterForm';
import { getPersonMax } from '@/pages/DataStatistics/feature/utils';
import { OperationReportDTO } from '../types';
interface IPData {
singles: any[];
groups: any[];
}
interface IProps<T> {
data: T & IPData;
timeDimension: OperationReportDTO['timeDimension'];
}
type FilterValuesType = {
endDate: string;
startDate: string;
timeDimension: OperationReportDTO['timeDimension'];
};
const makeOption = <T extends object>(props: IProps<T>) => {
const { data, timeDimension } = props;
if (!data?.singles) {
return {};
}
return {
color: ['#5590F6', '#44C69D', '#F69055', '#90F655'],
grid: { ...gridConfig, top: 12 },
tooltip: {
trigger: 'axis',
formatter(params: any) {
const startDate = params[0]?.name;
let endDate = '';
if (timeDimension === 2) {
endDate = dayjs(startDate.replace(/\./g, '/')).add(1, 'w').subtract(1, 'd').format(dateFormat1);
} else if (timeDimension === 3) {
endDate = dayjs(startDate.replace(/\./g, '/')).add(1, 'M').subtract(1, 'd').format(dateFormat1);
}
const date = endDate ? `${startDate} ~ ${endDate}` : startDate;
return `
<div>
<div>${date}</div>
${params
.map(
(p: any) =>
`<div style='display:flex;justify-content:space-between;'><span>${p.marker} ${p.seriesName}</span><span style='padding-left:20px;'>${p.value}</span></div>`
)
.join('')}
</div>`;
}
},
dataZoom: getZoomConfig(data?.singles),
xAxis: {
type: 'category',
data: data?.singles?.map((item: any) => item.date),
axisTick: {
alignWithLabel: true,
length: 0
},
axisLine: {
lineStyle: {
opacity: 0.2
}
}
},
yAxis: [
{
type: 'value',
axisLabel: {
formatter: `{value}`
},
splitLine: {
lineStyle: {
type: 'dashed'
}
},
max: () => {
return getPersonMax(data?.singles?.map((item: any) => Number(item.value || 0)));
}
}
],
series: [
{
name: '单聊',
...lineConfig,
tooltip: {
valueFormatter: (value: string) => {
return `${value}`;
}
},
data: data?.singles?.map((item: any) => {
return item.value;
})
},
{
name: '群聊',
...lineConfig,
lineStyle: {
color: '#44C69D',
width: 2,
type: 'solid'
},
tooltip: {
valueFormatter: (value: string) => {
return `${value}`;
}
},
data: data?.groups?.map((item: any) => {
return item.value;
})
}
]
};
};
export const ImSessionDataPanel = () => {
const [query, setQuery] = React.useState<Pick<OperationReportDTO, 'startDate' | 'endDate' | 'timeDimension'>>();
const { data: tempData, loading } = useRequest(() => query && getImSessionData(query), {
manual: false,
refreshDeps: [query]
});
const data = useMemo(() => tempData, [tempData]);
const handleChange = (values: FilterValuesType) => {
setQuery({
...values
});
};
return (
<Panel
title='IM会话'
extra={
<FilterForm
onChange={handleChange}
omitItems={['platform']}
/>
}
icon='iconsystem_general_line_3_group-chat|#1ac6ffa6|#1ac6ff'
>
<Spin spinning={loading}>
<div style={{ width: '100%', height: 300, overflow: 'auto', position: 'relative' }}>
{data?.singles?.length > 0 && (
<ReactEcharts
option={makeOption({ data, timeDimension: query?.timeDimension })}
notMerge
lazyUpdate
/>
)}
</div>
</Spin>
</Panel>
);
};
import dayjs from 'dayjs';
import _ from 'lodash-es';
export const makeDay7 = () => {
const date = dayjs(new Date());
return Array.from({ length: 7 }, (_, index) => {
return date.subtract(index).format('YYYY-MM-DD');
});
};
export const makeDefaultData = () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return Array.from({ length: 9 }, (_) => 0);
};
export const makeDayData = () => {
return Array.from({ length: 7 }, (_, index) => index);
};
export const makeDay8Column = () => {
return [1, 2, 3, 4, 5, 6, 7, 14, 30].map((item) => ({
key: item,
dataIndex: `dataIndex-${item}`,
title: '一些文本'
}));
};
export const makeWeek8Column = () => {
return Array.from({ length: 9 }, (_, index) => ({
key: index + 1,
dataIndex: `dataIndex-${index + 1}`,
title: '一些文本'
}));
};
export const makeMonth8Column = () => {
return Array.from({ length: 9 }, (_, index) => ({
key: index + 1,
dataIndex: `dataIndex-${index + 1}`,
title: '一些文本'
}));
};
export const filterData = <T = any>(data: T[] = [], pageSize: number, current: number): T[] => {
return _.chunk(data, pageSize)[current - 1];
};
export const isLessDay = <T extends dayjs.Dayjs>(date: [T, T], value: number): boolean => {
if (!date) {
return false;
}
return dayjs(date[0].valueOf())
.add(value - 1, 'd')
.isBefore(date[1]);
};
export const toNumber = (value: number): string => {
if (!value) {
return '0';
}
if (value < 999) {
return String(value || 0);
}
const reg = /(\d)(?=(?:\d{3})+$)/g;
return String(value).replace(reg, '$1,');
};
export const getPersonMax = <T extends number>(values: T[]): T => {
const maxValue = Math.max(...values);
const step = [5, 10, 50, 100, 500, 1000, 5000, 10000, 50000];
return step.find((s) => s > maxValue) as T;
};
export const formatTimeToHMS = (time: number) => {
const hour = Math.floor(time / 3600) || 0;
const minute = Math.floor((time % 3600) / 60) || 0;
const second = time % 60 || 0;
const hourStr = hour > 9 ? `${hour}` : `0${hour}`;
const minuteStr = minute > 9 ? `${minute}` : `0${minute}`;
const secondStr = second > 9 ? `${second}` : `0${second}`;
return `${hourStr}:${minuteStr}:${secondStr}`;
};
// 获取使用时长最大值
export const getTimeMax = <T extends number>(values: T[]): T => {
const maxValue = Math.max(...values);
const step = [5, 10, 15, 20, 25];
return step.find((s) => s > maxValue) as T;
};
// 获取使用次数最大值
export const getCountMax = <T extends number>(values: T[]): T => {
const maxValue = Math.max(...values);
const step = [5, 10, 50, 100, 500, 1000, 5000, 10000, 50000];
return step.find((s) => s > maxValue) as T;
};