import React, { useState } from "react" import PropTypes from "prop-types" import classNames from "classnames" import Icon from "../icon" import Popover, { IPopoverProps } from "../popover" import Checkbox from "../checkbox" import Radio from "../radio" import "./style" const prefix = "adui-table" const getFilteredValue = (val?: (string | number)[] | null) => { if (val === null || val === undefined || val.length === 0) { return ["all"] } return val } export interface ITableFilterProps { filteredValue?: (string | number)[] | null filterMultiple?: boolean filterSearchable?: boolean filterSearchCaseSensitive?: boolean filterSearchPlaceholder?: string filterSearchFunc?: ( input: string, item: { text: string; value: string | number } ) => boolean filterPopoverProps?: IPopoverProps filters?: Array<{ text: string; value: string | number }> | null filterVisible?: boolean | null onFilter?: ((value: (string | number)[]) => void) | null onFilterVisibleChange?: ((visible: boolean) => void) | null title?: React.ReactNode sortableAndFilterable?: boolean } /** * 表格筛选 */ const TableFilter: React.FC = ({ filterSearchable, filterSearchPlaceholder, filterSearchCaseSensitive, filterSearchFunc, filteredValue: filteredValueProp, filterMultiple, filterPopoverProps, filterVisible, filters: filtersProp, onFilter, onFilterVisibleChange, title, sortableAndFilterable, }: ITableFilterProps) => { if (!filtersProp) { return null } const [filteredValue, setFilteredValue] = useState( getFilteredValue(filteredValueProp) ) const [visible, setVisible] = useState(filterVisible || false) const [searchValue, setSearchValue] = useState("") // 相当于生命周期 getDerivedStateFromProps if ( filteredValueProp !== null && filteredValueProp !== undefined && JSON.stringify(filteredValue) !== JSON.stringify(getFilteredValue(filteredValueProp)) ) { setFilteredValue(getFilteredValue(filteredValueProp)) } if (typeof filterVisible === "boolean" && visible !== filterVisible) { setVisible(filterVisible) } const handleChange = ( filteredValueParam: (string | number) | (string | number)[] ) => { const newValue: any = filterMultiple && filteredValueParam ? filteredValueParam : [filteredValueParam] if (newValue.includes("all")) { newValue.splice(newValue.indexOf("all"), 1) } if (filteredValueProp === null) { setFilteredValue(getFilteredValue(newValue)) } if (onFilter) { if (filteredValueParam === "all") { onFilter([]) } else { onFilter(newValue) } } if (!filterMultiple) { // 延迟是为了让状态的变化在视觉上先被接受 setTimeout(() => { if (onFilterVisibleChange) { onFilterVisibleChange(false) } setVisible(false) }, 100) } } let popup if (filterSearchable) { popup = (
{ const { value } = e.target setSearchValue(value) }} />
) } const filters = searchValue ? filtersProp.filter((o) => { const { text } = o if (filterSearchFunc) { return filterSearchFunc(searchValue, o) } if (!filterSearchCaseSensitive) { return String(text) .toLocaleLowerCase() .includes(searchValue.toLocaleLowerCase()) } return String(text).includes(searchValue) }) : filtersProp if (filterMultiple) { popup = ( <> {popup} {!filters.length ? (
无匹配结果
) : ( {filters.map((item) => ( {item.text} ))} )} ) } else { popup = ( <> {popup} {!filters.length ? (
无匹配结果
) : ( 全部 {filters.map((item) => ( {item.text} ))} )} ) } return ( { if (typeof filterVisible !== "boolean") { setVisible(bool) } if (onFilterVisibleChange) { onFilterVisibleChange(bool) } }} popup={popup} trigger="click" placement="bottomLeft" {...filterPopoverProps} >
1 || filteredValue[0] !== "all"), })} > {!sortableAndFilterable ? title : null} {!sortableAndFilterable &&
}
) } TableFilter.propTypes = { /** * 是否多选 */ filterMultiple: PropTypes.bool, /** * 筛选是否支持搜索 */ filterSearchable: PropTypes.bool, /** * 筛选搜索开启大小写敏感搜索,默认为 false */ filterSearchCaseSensitive: PropTypes.bool, /** * 筛选搜索 placeholder */ filterSearchPlaceholder: PropTypes.string, /** * 筛选搜索的自定义 function */ filterSearchFunc: PropTypes.func, /** * 筛选 Popover props,会将此对象透传给 */ filterPopoverProps: PropTypes.object, /** * 可以从外部传入筛选的值,null, [], 都会识别为未筛选状态 */ filteredValue: PropTypes.array, /** * 筛选项,格式:[{ text: "朋友圈广告", value: '2' }] */ filters: PropTypes.any, /** * 从外部控制 filter Popover 的显示 */ filterVisible: PropTypes.bool, /** * 筛选时的 handler */ onFilter: PropTypes.func, /** * 筛选 popup visible 变化时的 handler,参数 (bool, col) */ onFilterVisibleChange: PropTypes.func, /** * title */ title: PropTypes.node, /** * sortableAndFilterable?: boolean */ sortableAndFilterable: PropTypes.bool, } TableFilter.defaultProps = { filterMultiple: false, filterSearchable: false, filterSearchCaseSensitive: false, filterSearchPlaceholder: "在筛选项中搜索", filterSearchFunc: undefined, filterPopoverProps: {}, filteredValue: null, filterVisible: null, filters: null, onFilter: null, onFilterVisibleChange: null, title: null, sortableAndFilterable: false, } export default TableFilter