129 lines
4.2 KiB
TypeScript
129 lines
4.2 KiB
TypeScript
import { ScrollView, Text, View } from '@tarojs/components'
|
|
import classnames from 'classnames'
|
|
import type { FC } from 'react'
|
|
import { useCallback, useMemo, useState } from 'react'
|
|
import Iconfont from '../iconfont/iconfont'
|
|
import InfiniteScroll from '../infiniteScroll'
|
|
import LoadMore, { LoadMoreStatus } from '../LoadMore'
|
|
import styles from './index.module.scss'
|
|
|
|
export interface ColumnsType {
|
|
title: string
|
|
dataIndex: string
|
|
width: string
|
|
key: string
|
|
render?: (text?: string, record?: RecordType, index?: number) => React.ReactNode
|
|
ellipsis?: boolean | { isEllipsis: boolean; rows: number }
|
|
}
|
|
|
|
export interface RecordType {
|
|
key: string
|
|
[Property: string]: any
|
|
}
|
|
|
|
export interface TablePropsType {
|
|
columns: ColumnsType[]
|
|
dataSource?: { list: RecordType[]; total: number }
|
|
onLoadMore?: () => void
|
|
height?: number
|
|
moreText?: string
|
|
loadingText?: string
|
|
noMoreText?: string
|
|
emptyText?: string
|
|
safeAreaInsetBottom?: boolean
|
|
}
|
|
|
|
const Table: FC<TablePropsType> = (props) => {
|
|
const { columns, dataSource, onLoadMore, height = 400, moreText = '查看更多', loadingText = '加载中', noMoreText = '没有更多了', emptyText = '暂无数据', safeAreaInsetBottom = true } = props
|
|
|
|
const handleShowMore = () => {
|
|
onLoadMore && onLoadMore()
|
|
}
|
|
|
|
const getColumnStyle = useCallback((columnConfig: ColumnsType) => {
|
|
const columnStyle = {}
|
|
if (typeof columnConfig.ellipsis === 'boolean' && columnConfig.ellipsis) {
|
|
columnStyle[styles.ellipsis_1] = true
|
|
}
|
|
if (typeof columnConfig.ellipsis === 'object' && columnConfig.ellipsis.isEllipsis) {
|
|
const rows = columnConfig.ellipsis.rows
|
|
if (rows === 2) {
|
|
columnStyle[styles.ellipsis_2] = true
|
|
}
|
|
else {
|
|
columnStyle[styles.ellipsis_1] = true
|
|
}
|
|
}
|
|
return columnStyle
|
|
}, [])
|
|
|
|
const loadMoreComponent = useMemo(() => {
|
|
if (dataSource) {
|
|
if (dataSource.list.length === 0 && dataSource.list.length === dataSource.total) {
|
|
return <LoadMore emptyText={emptyText} status="empty"></LoadMore>
|
|
}
|
|
else if (dataSource.list.length < dataSource.total) {
|
|
return <LoadMore moreText={moreText} status="more" onClick={handleShowMore}></LoadMore>
|
|
}
|
|
else if (dataSource.list.length >= dataSource.total) {
|
|
return <LoadMore noMoreText={noMoreText} status="noMore"></LoadMore>
|
|
}
|
|
}
|
|
else {
|
|
return <LoadMore moreText={moreText} loadingText={loadingText} noMoreText={noMoreText} status="loading"></LoadMore>
|
|
}
|
|
}, [dataSource])
|
|
|
|
const sourceContainer = () => {
|
|
return (
|
|
<>
|
|
{!!dataSource?.list?.length
|
|
&& dataSource.list.map((source) => {
|
|
return (
|
|
<View className={classnames(styles.tr, styles['bg-line'])} key={source.key}>
|
|
{columns.map((column, key) => {
|
|
if (column.render) {
|
|
return (
|
|
<View key={key} className={styles.td} style={{ width: column.width }}>
|
|
{/* 判断表头是不是有render 有就执行render */}
|
|
{column.render(source[column.dataIndex])}
|
|
</View>
|
|
)
|
|
}
|
|
else {
|
|
return (
|
|
<View key={key} className={classnames(styles.td, getColumnStyle(column))} style={{ width: column.width }}>
|
|
{
|
|
source[column.dataIndex] // 根据表头填数据
|
|
}
|
|
</View>
|
|
)
|
|
}
|
|
})}
|
|
</View>
|
|
)
|
|
})}
|
|
{loadMoreComponent}
|
|
</>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<View className={styles.table}>
|
|
<View className={classnames(styles.tr, styles['bg-header'])}>
|
|
{columns.map((column) => {
|
|
return (
|
|
<View className={styles.th} style={{ width: column.width }} key={column.key}>
|
|
{column.title}
|
|
</View>
|
|
)
|
|
})}
|
|
</View>
|
|
<InfiniteScroll enableLoadMoreStatus={false} safeAreaInsetBottom={safeAreaInsetBottom}>
|
|
{sourceContainer()}
|
|
</InfiniteScroll>
|
|
</View>
|
|
)
|
|
}
|
|
export default Table
|