import React, { memo, useMemo, useState, useCallback, useEffect, useRef } from 'react'
import Taro from '@tarojs/taro'
import {View} from '@tarojs/components-rn'
import { Animated, VirtualizedList } from 'react-native'
import {Block, Box, Flex, Line, Text, ScrollView, TextEllipsis, Press, TFlexWay} from '../Components'
import {getCloumnsItemByKey, reOrderDataSource, sortBy, getScreenData, screenBy, DEFAULT_HEIGHT, DEFAULT_WIDTH} from './utils'
import { RTX } from '../constants/constants'
// import TablePop from './TablePop'
export interface Column {
title: string
dataIndex: string
/** 是否启用排序 */
sort?: boolean
// /** 是否启用筛选 */
// screen?: boolean
/**
* 自定义渲染组件, text为当前的值,record为当前行的值,index为当前索引
* @example
* render: (text, record, index) => {
* return (
* {text||'0'}
* )
* }
*/
render?: any
/** 列表的宽度,当 scrollX为false 时,用%设置,且每个列都要设置%,,反之,请用数字 */
width?: string
/** 列表格的对其方式 同 Flex 一样 */
flex?: TFlexWay
/** 列表的颜色,半透明 */
columnBgColor?: string
/** 列表里面,字显示多少行后,进行省略 */
textLine?: string
}
interface TableProps {
/** 表的ID,唯一 */
id: string
/** 列表格式 */
columns: Column[]
/** 数据源 */
dataSource: any
// /** x轴 是否可以滚动 */
// scrollX?: boolean
/** 选择的行,的背景色,rgba透明的 */
selectLineColor?: string
/** 表格主题色 */
themeColor?: string
/** 标题栏,背景色 */
titleBgColor?: string
/** 使用 Taro.nextTick 确保本次 setState 不会和首次渲染合并更新,优化加载 */
mounted?: boolean
/** 行高,设置后,列表高度将固定。开启虚拟化时,这个为必填 */
rowHeight?: string
/** 虚拟化表格的尺寸, 值必须为具体数值,如:'750 600',当 virtualSize 有值时,表示启用虚拟化表格功能,且 rowHeight 此时必须有具体的值 */
virtualSize?: string
/** 普通表格的尺寸(默认为 '100% 100%')。如果设置了 virtualSize,则 size 将不生效 */
size?: string
/** 虚拟列表的 预加载列数 默认为1行 */
overscanCount?: string
/** table 的圆角 */
radius?: string
/** 排序箭头,未激活 */
IconSort?: React.ReactNode
/** 排序箭头,激活 */
IconSortActive?: React.ReactNode
/** 筛选,未激活 */
IconScreen?: React.ReactNode
/** 筛选,激活 */
IconScreenActive?: React.ReactNode
/** 复选框,未激活 */
IconSelect?: React.ReactNode
/** 复选框,激活 */
IconSelectActive?: React.ReactNode
/** 表格里面的字体大小 */
fontSize?: string
/** 表格里面的字体颜色 */
color?: string
/** 表格标题分栏的线条颜色, 和进度条底色 */
lineColor?: string
/** 行分隔颜色,浅色 */
rowBgColorLight?: string
/** 行分隔颜色,深色 */
rowBgColor?: string
/** 每个小方格的 padding */
itemPadding?: string
/** 每行数据,唯一ID */
rowKey?: string
/** 是否正在加载 */
loading?: boolean
}
const Table = ({
dataSource, id, columns, scrollX=false, selectLineColor='rgba(255, 195, 0, 0.19)',
themeColor='#1890ff', titleBgColor='rgba(255, 255, 255, 1)', mounted=true, rowHeight, overscanCount='1', radius='0',
IconSort, IconScreen, IconSortActive, IconScreenActive, fontSize='32', color='#060606', hoverColor='#f2f2f2', lineColor='#ededed',
rowBgColor='#ffffff', rowBgColorLight='#f5f5f5', IconSelect, IconSelectActive, size='100% 100%',
itemPadding='15 8 15 8', loading, virtualSize, rowKey='id'
}: TableProps) => {
const [percent, setPercent] = useState(30) // 加载中,动画
const [newDataSource, setNewDataSource] = useState([{}])
const [selectItem, setSelectItem] = useState<{row: number; col: string;}>({row: -1, col: '', }) // 行index, 列 dataIndex
const [sortColumn, setSortColumn] = useState<{colKey: string; sortBy: -1 | 0 | 1; }>({
colKey: '',
sortBy: 0, // -1 为降序排列,, 0 为不排列,, 1 为升序排列
})
const [showScreen, setShowScreen] = useState<{show: 1 | 0 | -1; left: string; top: string; width: string; selectKey: string | number;}>({
selectKey: '',
show: 0,
left: '0',
top: '80',
width: DEFAULT_WIDTH,
}) // 是否显示筛选的面板
// 将筛选的数据列出来
const [screenData, setScreenData] = useState<{[key: string]: any;}>({})
const animatedValue = useRef(new Animated.Value(0)).current
const rIn = () => {
Animated.timing(animatedValue, {
toValue: 1,
duration: 300,
useNativeDriver: true
}).start()
}
const rOut = () => {
Animated.timing(animatedValue, {
toValue: 0,
duration: 300,
useNativeDriver: true
}).start()
}
useEffect(() => {
setPercent(100)
}, [mounted])
useEffect(() => {
setNewDataSource(reOrderDataSource(dataSource, columns))
setScreenData(getScreenData(dataSource, columns))
}, [columns, dataSource])
const dataSourceBackup = useMemo(() => {
return reOrderDataSource(dataSource, columns)
}, [columns, dataSource])
/**
* 排序变化
*/
const onSortColumn = useCallback((col: string) => {
if(col !== sortColumn.colKey && sortColumn.colKey){
setSortColumn({
colKey: col,
sortBy: -1,
})
rOut()
}else{
switch(sortColumn.sortBy) {
case 0:
setSortColumn({
colKey: col,
sortBy: -1,
})
rOut()
return
case -1:
setSortColumn({
colKey: col,
sortBy: 1,
})
rIn()
return
case 1:
setSortColumn(prev => ({
...prev,
}))
rOut()
setTimeout(() => {
setSortColumn(prev => ({
...prev,
colKey: '',
sortBy: 0, // -1 为降序排列,, 0 为不排列,, 1 为升序排列
}))
}, 300)
return
default:
return
}
}
}, [sortColumn.sortBy, sortColumn.colKey, selectLineColor, themeColor, rIn, rOut])
/**
* 筛选变化
*/
// 筛选按钮的点击回调
const screenClick = useCallback((item, index, type) => {
// onScreenColumn(item.dataIndex)
if(showScreen.show === 1){
setShowScreen(prev => ({
...prev,
show: 0,
}))
}else{
let leftDis = 0
for(let i = 0; i < columns.length; i++){
if(i < index){
leftDis += parseInt(columns[i].width || DEFAULT_WIDTH)
}
}
setShowScreen(prev => ({
...prev,
selectKey: item.dataIndex,
show: 1,
left: '33',
// top: `${(res[0].scrollTop * rtx + 80) >>> 0}`,
width: item.width || DEFAULT_WIDTH
}))
}
}, [showScreen.show, columns, id])
// 执行 排序 和 筛选
useEffect(() => {
if(showScreen.show !== 1){
let tempChange: any[] = []
// 先执行排序
if(sortColumn.sortBy === 0){
tempChange = dataSourceBackup
}else{
tempChange = sortBy(dataSourceBackup, sortColumn.colKey, sortColumn.sortBy)
}
// 再进行筛选
for(let skey in screenData){
if(skey[0] === '_' && screenData[skey].length > 0){
tempChange = screenBy(tempChange, skey.substring(1), screenData[skey])
}
}
setNewDataSource(tempChange)
setPercent(100)
}
}, [screenData, sortColumn.sortBy, sortColumn.colKey, dataSourceBackup, showScreen.show])
// 标题栏
const RowTitle = (
{
scrollX ?
{
columns.map((item, index) => (
{
item.sort ?
{
if(showScreen.show === 1){
setShowScreen(prev => ({
...prev,
show: 0
}))
}else{
onSortColumn(item.dataIndex)
}
}}
>
{item.title}
{
sortColumn.colKey === item.dataIndex ?
{IconSortActive}
:
IconSort
}
:
item.screen ?
{
screenClick(item, index, 1)
setPercent(0)
}}
>
{item.title}
{
screenData['_' + item.dataIndex]?.length > 0 ?
IconScreenActive
:
IconScreen
}
:
{
if(showScreen.show === 1){
setShowScreen(prev => ({
...prev,
show: 0
}))
}
}}
>
{item.title}
}
))
}
:
{
columns.map((item, index) => (
{
item.sort ?
{
if(showScreen.show === 1){
setShowScreen(prev => ({
...prev,
show: 0
}))
}else{
onSortColumn(item.dataIndex)
}
}}
>
{item.title}
{
sortColumn.colKey === item.dataIndex ?
{IconSortActive}
:
IconSort
}
:
item.screen ?
{
screenClick(item, index, 2)
setPercent(0)
}}
>
{item.title}
{
screenData['_' + item.dataIndex]?.length > 0 ?
IconScreenActive
:
IconScreen
}
:
{
if(showScreen.show === 1){
setShowScreen(prev => ({
...prev,
show: 0
}))
}
}}
>
{item.title}
}
))
}
}
)
// 行数据
const RowData = (
{
scrollX ?
newDataSource.map((item, index) => (
{
Object.entries(item).map(([key, value]: any) => {
if(key.includes('_column_')) return null
const tempColumn = getCloumnsItemByKey(columns, key)
return (
{
// 隐藏筛选面板
if(showScreen.show === 1){
setShowScreen(prev => ({
...prev,
show: 0
}))
}else{
if(selectItem.row === index){
setSelectItem({
row: -1,
col: '',
})
}else{
setSelectItem({
row: index,
col: key,
})
}
}
}}
size={`${tempColumn.width || DEFAULT_WIDTH} auto`}
bgColor={tempColumn.columnBgColor || ''}
>
{
tempColumn.render ?
tempColumn.render(newDataSource, item._column_item_record, index)
:
{value}
}
)
})
}
))
:
newDataSource.map((item, index) => (
{
Object.entries(item).map(([key, value]: any) => {
if(key.includes('_column_')) return null
const tempColumn = getCloumnsItemByKey(columns, key)
return (
{
// 隐藏筛选面板
if(showScreen.show === 1){
setShowScreen(prev => ({
...prev,
show: 0
}))
}else{
if(selectItem.row === index){
setSelectItem({
row: -1,
col: '',
})
}else{
setSelectItem({
row: index,
col: key,
})
}
}
}}
>
{
tempColumn.render ?
tempColumn.render(newDataSource, item._column_item_record, index)
:
{value}
}
)
})
}
))
}
)
return(
{
if(showScreen.show === 1){
setShowScreen(prev => ({
...prev,
show: 0
}))
}
}}
>
{RowTitle}
{
virtualSize ?
{
loading ?
加载中...
:
dataSource.length === 0 ?
暂无内容
: null
}
item[rowKey]}
renderItem={({item, index}) => (
{
Object.entries(item).map(([key, value]: any) => {
if(key.includes('_column_')) return null
const tempColumn = getCloumnsItemByKey(columns, key)
return (
{
// 隐藏筛选面板
if(showScreen.show === 1){
setShowScreen(prev => ({
...prev,
show: 0
}))
}else{
if(selectItem.row === index){
setSelectItem({
row: -1,
col: '',
})
}else{
setSelectItem({
row: index,
col: key,
})
}
}
}}
>
{
tempColumn.render ?
tempColumn.render(newDataSource, item._column_item_record, index)
:
{value}
}
)
})
}
)}
getItemCount={(data: any) => data.length}
getItem={(data, index) => data[index]}
windowSize={(+(rowHeight || DEFAULT_HEIGHT) * RTX) * +overscanCount}
getItemLayout={(data, index) => ({length: data.length, offset: index * (+(rowHeight || DEFAULT_HEIGHT) * RTX), index: index})}
/>
:
{RowData}
{
loading ?
加载中...
:
dataSource.length === 0 ?
暂无内容
: null
}
{/* {
setScreenData(prev => ({
...prev,
[`_${showScreen.selectKey}`]: selectList
}))
}}
left={showScreen.left}
top={showScreen.top}
width={showScreen.width}
lineColor={lineColor}
titleBgColor={titleBgColor}
hoverColor={hoverColor}
IconSelect={IconSelect}
IconSelectActive={IconSelectActive}
color={color}
fontSize={fontSize}
/> */}
}
)
}
export default memo(Table) as React.ElementType