import React, { useState, useEffect } from "react";
import { Row, Col, Input, Select, DatePicker, Button, Tooltip } from "antd";
import { Const } from "src/utils/const";
const { Option } = Select;
const { RangePicker } = DatePicker;
interface IFilters {
// 公共筛选组件
label: string; // 筛选名称
key: string; // 筛选的字段
defaultValue?: any; // 默认值
type: string; // 选项的类型:Input-输入框,NumberInput-数字输入框,Select-下拉框,SelectMultiple-下拉框多选,Date-日期,DateRange-日期范围,DateRangeButton-按钮日期
options?: { name: string; value: any }[]; // 下拉框的可选项, 如果是DateRangeButton,value为const中DATE_PICKER_RANGER_HELPER的key
span?: number; // 列宽,总共24
tip?: string; // 文案提示
render?: () => any; // 自定义渲染选项
onChange?: (data: any) => any;
}
interface IFilterFormProps {
filterColumns: IFilters[][]; // 一个数组代表一行
onSubmit: (data: any) => any;
onChange?: (data: any) => any;
className?: string;
changeFieldsValue?: any; // 联动字段
}
const FilterForm: React.FunctionComponent<IFilterFormProps> = (props: IFilterFormProps) => {
const { filterColumns } = props;
const [filterValues, setFilterValues] = useState();
// 初始化
useEffect(() => {
initFilterValues();
}, []);
useEffect(() => {
if (props.changeFieldsValue) {
const values = filterValues ? { ...filterValues } : {};
Object.keys(props.changeFieldsValue).map(item => {
values[item] = props.changeFieldsValue[item];
});
setFilterValues(values);
}
}, [props.changeFieldsValue]);
const initFilterValues = () => {
const values = {};
filterColumns.map(rows => {
rows.map(item => {
values[item.key] = item.defaultValue;
});
});
setFilterValues(values);
};
const onFieldsChange = (filter: IFilters, value: any) => {
const values = { ...filterValues };
const field = filter.key;
// Just because an empty array or string means all.
values[field] = String(value).length ? value : void 0;
setFilterValues(values);
if (filter.onChange) {
filter.onChange(value);
}
if (props.onChange) {
props.onChange(values);
}
};
const resetFields = () => {
initFilterValues();
};
const renderTooltip = (text: string) => {
return (
<Tooltip placement="topLeft" title={text}>
<Button icon="question-circle" type="link" size="small" />
</Tooltip>
);
};
const renderDateRange = (filter: IFilters, text: string, range: any) => {
return (
<Button
key={text}
style={{ marginLeft: 10 }}
onClick={() => {
onFieldsChange(filter, range);
}}
>
{text}
</Button>
);
};
// 选项的类型:Input-输入框,NumberInput-数字输入框,Select-下拉框,SelectMultiple-下拉框多选,
// Date-日期,DateRange-日期范围
// 根据需求定义更多类型
const renderForm = (filter: IFilters) => {
const filterItem = {
Input: (
<Input
value={filterValues ? filterValues[filter.key] : undefined}
className="full-width"
placeholder={filter.label}
onChange={e => onFieldsChange(filter, e.target.value)}
/>
),
NumberInput: (
<Input
value={filterValues ? filterValues[filter.key] : undefined}
className="full-width"
placeholder={filter.label}
onChange={e => {
if (!e.target.value) {
onFieldsChange(filter, undefined);
} else if (!Number.isNaN(Number(e.target.value)) && /^\d+$/.test(e.target.value)) {
onFieldsChange(filter, Number(e.target.value));
}
}}
/>
),
Select: (
<Select
value={filterValues ? filterValues[filter.key] : undefined}
className="full-width"
placeholder={filter.label}
allowClear={true}
filterOption={(input: string, option: any) => {
try {
return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
} catch {
return option.props.children.indexOf(input) >= 0;
}
}}
onChange={(value: any) => onFieldsChange(filter, value)}
>
{filter.options
? filter.options.map((item: any) => {
return (
<Option key={item.value} value={item.value}>
{item.name}
</Option>
);
})
: null}
</Select>
),
SelectMultiple: (
<Select
value={filterValues ? filterValues[filter.key] : undefined}
className="full-width"
mode="multiple"
allowClear={true}
placeholder={filter.label}
filterOption={(input: string, option: any) => {
try {
return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
} catch {
return option.props.children.indexOf(input) >= 0;
}
}}
onChange={(value: any) => onFieldsChange(filter, value)}
>
{filter.options
? filter.options.map((item: any) => {
return (
<Option key={item.value} value={item.value}>
{item.name}
</Option>
);
})
: null}
</Select>
),
Date: (
<DatePicker
value={filterValues ? filterValues[filter.key] : undefined}
onChange={value => onFieldsChange(filter, value)}
/>
),
DateRange: (
<RangePicker
value={filterValues ? filterValues[filter.key] : undefined}
onChange={value => onFieldsChange(filter, value)}
/>
),
};
return filterItem[filter.type];
};
return (
<div className={props.className}>
{filterColumns.map((rows, index) => (
<Row gutter={8} key={index}>
{rows.map(filter => (
<span key={filter.key}>
<Col span={2} className="form-label">
{filter.label}
{filter.tip ? renderTooltip(filter.tip) : null}:
</Col>
<Col span={filter.span ? filter.span : 4} className="margin-bottom-sm">
{filter.render ? filter.render() : renderForm(filter)}
</Col>
</span>
))}
</Row>
))}
<div className="pull-right">
<Button className="margin-right-sm btn-warning" onClick={() => props.onSubmit(filterValues)}>
查询
</Button>
<Button type="danger" onClick={() => resetFields()}>
重置
</Button>
</div>
</div>
);
};
export default FilterForm;
// 引用表单测试
import React, { useState } from "react";
import moment from "moment";
import FilterForm from "src/components/public/filter-form";
interface ITestFilters {
onFilter: (params: any) => void;
defaultFilters: any;
}
const TestFilters: React.FunctionComponent<ITestFilters> = (props: ITestFilters) => {
const [changeFieldsValue, setChangeFieldsValue] = useState<any>();
const test2=[...];
const changeTest3 = (id: number) => {
...
setChangeFieldsValue({Test3:""})
};
const onSubmit = (filters: any) => {
...
}
const { StartTime, EndTime } = props.defaultFilters;
const filterColumns: IFilters[][] = [
[
{
label: "Test1",
key: "Test1",
type: "NumberInput"
},
{
label: "Test2",
key: "Test2",
type: "Select",
options: test2.map((item: any) => {
return { name: item.Name, value: item.Id };
}),
},
],
[
{
label: "Test3",
key: "Test3",
type: "Date",
defaultValue: StartTime,
onChange: changeTest3
},
{
label: "Test4",
key: "Test4",
type: "Date",
defaultValue: EndTime,
},
......
]
];
return <FilterForm filterColumns={filterColumns} changeFieldsValue={changeFieldsValue} onSubmit={onSubmit} />;
};
export default TestFilters;
我这里用的是ts,用js的也差的不多,react是新版的hook,省略了一些代码,思想基本都体现出来了