import classNames from 'classnames' import dayjs from 'dayjs' import { useState, useEffect } from 'react' import './index.less' enum ModeType { LINE = 'line', CARD = 'card' } type TimeLineListProps = { rowKey?: ((item: T) => React.Key) | keyof T dataSource: T[] renderItem?: (item: T, index: number) => React.ReactNode dataField: keyof T mode: 'line' | 'card' } function TimeLineList({ dataField = 'createTime', dataSource = [], mode = 'line', renderItem }: TimeLineListProps) { // 用二维数组去存数据 const [dataMap, setDataMap] = useState>(null) useEffect(() => { const formatTimeMap = () => { // 先去重,按日期进行分组 const uniKeys = Array.from(new Set(dataSource.map(item => item?.[dataField]))) const uniDataMap = [] // 构建二维数组 uniKeys.forEach(key => { uniDataMap.push(dataSource.filter(item => item?.[dataField] === key)) }) setDataMap(uniDataMap) } dataSource?.length && formatTimeMap(dataSource) }, [dataSource]) if (!dataMap) return null // 渲染左侧日期 const renderDate = (dataIndex: number, diffTime: number, renderTime: dayjs.Dayjs) => { let node = null if (dataIndex === 0) { switch (diffTime) { case 0: node = '今天' break case 1: node = '昨天' break case 2: node = renderTime.format('MM-DD') break default: node = (
{renderTime.get('year')} {renderTime.format('MM-DD')}
) break } } return node } // render mode timeline const renderTimelineItem = () => { return dataMap.map(t => t.map((item, i) => { const itemTime = dayjs(item?.[dataField]) const currentTime = dayjs() if (itemTime && currentTime) { const renderTime = currentTime.diff(itemTime, 'day') return (
0 ? 'time-item-label-square' : 'time-item-label-base', { 'time-item-label-forward': renderTime <= 2 })}> {renderDate(i, renderTime, itemTime)}
{renderItem?.(item, i)}
) } return null }) ) } // render mode card const renderCardItem = () => { return dataMap.map(t => t.map((item, i) => { const itemTime = dayjs(item?.[dataField]) const currentTime = dayjs() if (itemTime && currentTime) { const renderTime = currentTime.diff(itemTime, 'day') return (
{renderDate(i, renderTime, itemTime)}
{renderItem?.(item, i)}
) } return null }) ) } return (
{mode === ModeType.LINE ? renderTimelineItem() : renderCardItem()}
) } export default TimeLineList