UNPKG

cjd-parkball

Version:

> 中后台业务组件库,中后台就像公园,进入需要买门票(登录),所以以 Parkball(公园球) 命名,公园内必定捕获!作为一个组件库,提供使用方法文档,方便开发者的调用

506 lines (500 loc) 13.3 kB
import { Button, Checkbox, Col, DatePicker, Form, Input, Pagination, Row, Select, message } from 'antd' import classnames from 'classnames' import PropTypes from 'prop-types' import React, { isValidElement } from 'react' import moment from 'moment' import { request } from '../utilities' import './index.scss' const { Item: FormItem } = Form const { Option } = Select const { RangePicker } = DatePicker message.config({ top: 99, duration: 1, maxCount: 1, }) let timeout = null function delay (c, ms) { if (timeout) { clearTimeout(timeout) } timeout = setTimeout(c, ms) } class FilterTable extends React.Component { static propTypes = { className: PropTypes.string, size: PropTypes.string, agile: PropTypes.bool, handlers: PropTypes.arrayOf(PropTypes.oneOfType([ PropTypes.string, PropTypes.element, ])), showHandlers: PropTypes.bool, onSearch: PropTypes.func, onReset: PropTypes.func, items: PropTypes.arrayOf(PropTypes.oneOfType([ PropTypes.string, PropTypes.shape({ name: PropTypes.string, label: PropTypes.string, placeholder: PropTypes.string, itemType: PropTypes.oneOf(['input', 'select', 'combobox', 'datePicker', 'checkbox']), subType: PropTypes.oneOf(['time', 'date', 'week', 'month', 'range']), selectOptions: PropTypes.arrayOf(PropTypes.shape({ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), label: PropTypes.string, })), buildOptions: PropTypes.func, disabled: PropTypes.bool, hidden: PropTypes.bool, defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool, PropTypes.array]), onChange: PropTypes.func, valueFormat: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), nameFormat: PropTypes.func, rules: PropTypes.arrayOf(PropTypes.object), }), ])), pagination: PropTypes.object, } static defaultProps = { className: '', size: 'medium', agile: false, handlers: ['重置', '搜索'], showHandlers: true, onReset: () => { console.log('default onReset handler') }, onSearch: () => { console.log('default onSearch handler') }, items: [], pagination: { total: 0, pageNo: 1, pageSize: 20, }, } constructor (props) { super(props) const { items, pagination } = props this.state = { items, pagination: { total: 0, pageNo: 1, pageSize: 20, ...pagination, }, } } combineItems = (fresh) => { const { getFieldError, setFields } = this.props.form const { items: origin } = this.state const combined = origin.map((o) => { for (let i = 0; i < fresh.length; i += 1) { const f = fresh[i] if (f.name === o.name) { if (getFieldError(o.name)) { setFields({ [o.name]: { errors: null } }) } return { ...o, ...f } } } return o }) this.setState({ items: combined }) } onFieldsChange (field) { const { item, value, option, event, } = field const { type, onChange, onSelect } = item const { agile } = this.props if (agile) { this.intendSearch() } switch (type) { case 'select': case 'combobox': onSelect && onSelect({ value, option, combineItems: this.combineItems }) break case 'picker': onChange && onChange({ value, combineItems: this.combineItems }) break default: onChange && onChange({ value, event, combineItems: this.combineItems }) break } } buildPagination () { const { pagination } = this.state const { pageNo, pageSize } = pagination const { total } = this.props.pagination return ( <Pagination total={total} current={pageNo} pageSize={pageSize} onChange={this.intendChangePage} /> ) } buildSelect (item) { const { placeholder, disabled, url, selectOptions, buildOptions, name, } = item if (!Array.isArray(selectOptions) && url && buildOptions) { request(url) .then((r) => { this.combineItems([{ name, selectOptions: buildOptions(r) }]) }) } const options = (selectOptions || []).map(o => <Option key={o.value}>{o.label}</Option>) return ( <Select disabled={!!disabled} placeholder={placeholder || '请选择'} onSelect={(value, option) => { this.onFieldsChange({ item, value, option }) }} > {options} </Select> ) } buildCheckbox (item) { const { disabled, defaultValue } = item return ( <Checkbox disabled={!!disabled} onChange={(event) => { const { checked: value } = event.target; this.onFieldsChange({ item, value, event }) }} defaultChecked={!!defaultValue} /> ) } buildCombobox (item) { const { placeholder, disabled, onChange, url, selectOptions, buildOptions, name, } = item if (!Array.isArray(selectOptions) && url && buildOptions) { request(url) .then((r) => { this.combineItems([{ name, selectOptions: buildOptions(r) }]) }) } const options = (selectOptions || []).map(o => <Option key={o.value}>{o.label}</Option>) return ( <Select showSearch disabled={!!disabled} showArrow={false} placeholder={placeholder || '请输入'} filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0} onSearch={(v, e) => { if (url) { delay(() => { request(url + v) .then((r) => { onChange && onChange(v, r, e) buildOptions && this.combineItems([{ name, selectOptions: buildOptions(r) }]) }) }, 500) return } onChange && onChange(v, e) }} onSelect={(value, option) => { this.onFieldsChange({ item, value, option }) }} > {options} </Select> ) } /* eslint-disable consistent-return */ buildDatePicker (item) { const { subType, disabled, placeholder, } = item if (subType === 'range') { return ( <RangePicker placeholder={placeholder || ['请选择', '请选择']} disabled={!!disabled} onChange={(moments, value) => { this.onFieldsChange({ item, value }) }} /> ) } } buildInput (item) { const { placeholder, disabled } = item return ( <Input placeholder={placeholder || '请输入'} disabled={!!disabled} onChange={(event) => { const { value } = event.target; this.onFieldsChange({ item, value, event }) }} /> ) } fieldMap (item) { const { type } = item switch (type) { case 'select': return this.buildSelect(item) case 'combobox': return this.buildCombobox(item) case 'datePicker': return this.buildDatePicker(item) case 'checkbox': return this.buildCheckbox(item) default: return this.buildInput(item) } } /* eslint-disable class-methods-use-this */ getValueFromEvent (t) { if (t === 'checkbox') { return { getValueFromEvent (e) { return e.target.checked } } } } buildItem (item) { const { getFieldDecorator, fieldsNameFormat } = this.props.form if (typeof item === 'object') { const { type, subType, name, label, defaultValue: initialValue, rules, nameFormat, } = item if (nameFormat) { this.props.form.fieldsNameFormat = { ...fieldsNameFormat, [name]: nameFormat, } } return ( <FormItem colon={false} key={name} label={label} > { getFieldDecorator(name, { initialValue, rules, ...this.getValueFromEvent(type, subType), })(this.fieldMap(item)) } </FormItem> ) } } buildItemCol () { const { items } = this.state const { showHandlers } = this.props let span = 8 if (!showHandlers) { span = 6 } return items.map((item, i) => { return ( <Col key={i} span={span} className="item-col" > {this.buildItem(item)} </Col> ) }) } buildItemRow () { return ( <Row type="flex" justify="start" className="items-row" > {this.buildItemCol()} </Row> ) } /* eslint-disable class-methods-use-this, consistent-return */ buildHandler (handler, callback, type) { if (typeof handler === 'string') { return ( <Button type={type} onClick={callback} > {handler} </Button> ) } if (isValidElement(handler)) { return handler } } valuesFormat (value, item) { const { type, valueFormat } = item if (valueFormat) { return valueFormat(value) } if (type === 'datePicker') { return value.map(v => moment(v).format('YYYY-MM-DD')) } } validateItems () { const { form } = this.props const { fieldsNameFormat, validateFields } = form const { items } = this.state let values = null validateFields({ first: true, force: true, }, (err, vals) => { if (err) { const info = Object.values(Object.values(err)[0])[0][0].message message.error(info) return } values = {} Object.entries(vals).forEach((field) => { const k = field[0] const v = field[1] if (v !== undefined && v !== null) { if (fieldsNameFormat && fieldsNameFormat[k]) { const item = items.filter(({ name }) => name === k)[0] values = { ...values, ...fieldsNameFormat[k](this.valuesFormat(vals[k], item)) } } else { values[k] = v } } }) }) return values } doReset = () => { const { form, onReset } = this.props const { resetFields, getFieldsValue } = form const { pagination } = this.state const { pageSize } = pagination this.setState({ pagination: { ...pagination, pageNo: 1 } }) resetFields() const params = { ...getFieldsValue(), pageNo: 1, pageSize } onReset && onReset(params) } doSearch (params) { const { onSearch } = this.props onSearch && onSearch(params) } intendSearch = () => { const vals = this.validateItems() if (vals) { const { pageNo, pageSize } = this.state.pagination this.doSearch({ ...vals, pageNo, pageSize }) } } intendChangePage = (pageNo, pageSize) => { const vals = this.validateItems() if (vals) { const { pagination } = this.state this.doSearch({ ...vals, pageNo, pageSize }) this.setState({ pagination: { ...pagination, pageNo, pageSize } }) } } buildHandlerCol () { const { handlers } = this.props return handlers.map((handler, i) => { let c = null let t = 'default' if (i === 0) { c = this.doReset } if (i === 1) { c = this.intendSearch t = 'primary' } return ( <Col key={i} className="handler-col" > {this.buildHandler(handler, c, t)} </Col> ) }) } buildHandlerRow () { return ( <Row type="flex" justify="end" className="handlers-row" > {this.buildHandlerCol()} </Row> ) } buildForm () { const { showHandlers } = this.props if (!showHandlers) { return ( <Form> <Row> <Col className="items-col"> {this.buildItemRow()} </Col> </Row> </Form> ) } return ( <Form> <Row> <Col span={20} className="items-col"> {this.buildItemRow()} </Col> <Col span={4} className="handlers-col"> {this.buildHandlerRow()} </Col> </Row> </Form> ) } // componentWillReceiveProps (nextProps) { // const { pagination } = nextProps // console.log(this.props.pagination) // console.log(nextProps.pagination) // } render () { const { className, size, table, tableFooter, } = this.props return ( <div className={classnames('parkball-filter-table', size, className)} > {this.buildForm()} {table} <div className="parkball-filter-table-footarea"> <div className="table-footer"> {tableFooter} </div> <div style={{ marginTop: '10px' }}>{this.buildPagination()}</div> </div> </div> ) } } export default Form.create({ onFieldsChange (props, field, fields) { // console.log(this) // console.log(props, field, fields) }, onValuesChange (props, field, fields) { // console.log(this) // console.log(props, field, fields) }, })(FilterTable)