UNPKG

hc-components

Version:

基于react的通用组件库

227 lines (206 loc) 6.67 kB
import React from 'react'; import PropTypes from 'prop-types'; import Form from 'antd/lib/form'; import Row from 'antd/lib/row'; import Col from 'antd/lib/col'; import Icon from 'antd/lib/icon'; import {CustomForm} from '../customForm'; import Divider from 'material-ui/Divider'; import './index.less'; class IArchive extends React.PureComponent { static propTypes = { options: PropTypes.array, dataSource: PropTypes.object, limit: PropTypes.number, form: PropTypes.object, cols: PropTypes.number, readonly: PropTypes.bool, compact: PropTypes.bool, layout: PropTypes.string, formItemLayout: PropTypes.object, onChange: PropTypes.func, onSubmit: PropTypes.func, formatter: PropTypes.func, noLabel: PropTypes.bool, style: PropTypes.object, className: PropTypes.string, buttons: PropTypes.array, buttonProps: PropTypes.object } static defaultProps = { options: [], dataSource: {}, cols: 3, readonly: true, compact: false, buttonProps: {noButton: true}, className: '', style: {} } constructor(props, context) { super(props, context); this.state = { expand: !props.limit || props.limit > props.options.length, dataSource: this.props.dataSource }; } componentWillReceiveProps(nextProps) { if (nextProps.dataSource !== this.props.dataSource) { this.setState({dataSource: nextProps.dataSource}); } } getFieldValue(name, option, editable) { let value; if (this.state.dataSource[name] === undefined) { value = option.value; } else { value = this.state.dataSource[name]; } if (this.props.formatter) { return this.props.formatter(value, option); } else { if (editable) { return option.renderInput ? option.renderInput(value, this.state.dataSource) : value; } else { return option.render ? option.render(value, this.state.dataSource) : value; } } } getFieldInput(name, option) { const {form, readonly, onChange} = this.props; const editable = option.editable === undefined ? !readonly : option.editable; if (editable) { /** * option = { * dataType | type, * enum, * options, * format, * mode, * dragger, * action, * valuePropName, * Component, * max, * maxLength, * maximum, * disabled, * placeholder * } */ const decorator = option.decorator || {}; if (onChange) { decorator.getValueFromEvent = (e) => { const v = CustomForm.getValueFromEvent(e, option); onChange(v, name); return v; }; } decorator.defaultValue = this.getFieldValue(name, option, editable); const stateProps = option.getProps && option.getProps.call(this, this.props, this.state.dataSource, (nextState) => { this.setState({ dataSource: Object.assign({}, this.state.dataSource, nextState) }); }, this.props.form); if (stateProps === false) return null; const fieldInput = CustomForm.getFieldInput(option, option.props, stateProps || {}, decorator); return form.getFieldDecorator(name, decorator)(fieldInput); } else { return this.getFieldValue(name, option); } } getFields() { const {options, limit, cols, formItemLayout, compact, noLabel} = this.props; const span = Math.floor(24 / cols); const count = this.state.expand ? options.length : limit; // const {getFieldDecorator} = form; const fields = []; const itemStyle = compact ? {marginBottom: 0} : {}; let item; let name; let label; let input; for (let i = 0; i < count; i++) { item = options[i]; if (item && (item.dataIndex || item.name)) { name = item.dataIndex || item.name; label = noLabel ? null : (item.title || item.name); input = this.getFieldInput(name, item); if (input) { fields.push( <Col span={item.col ? item.col * span : item.span || span} key={name} style={{display: i < count ? 'block' : 'none'}}> <Form.Item {...formItemLayout} {...item.attrs} label={label} style={itemStyle}> {input} </Form.Item> </Col> ); } } } return fields; } toggle = () => { this.setState({expand: !this.state.expand}); } handleSubmit = (e) => { e && e.preventDefault(); this.props.form.validateFields((err, values) => { if (!err) { this.props.options.forEach(option => { if (option.getValue) { const name = option.dataIndex || option.name; values[name] = option.getValue(values[name]); } }); this.props.onSubmit && this.props.onSubmit(values); } }); } getButtons() { const {buttons, buttonProps} = this.props; if (buttonProps.onSubmit) { buttonProps.onSubmit.bind(this.state.dataSource); } else { buttonProps.onSubmit = this.handleSubmit; } const justify = buttonProps.align || 'end'; const _buttons = CustomForm.getButtons(buttons, buttonProps); return _buttons ? (<Row justify={justify} type="flex" className="o-com-archive_btns" style={buttonProps.btnStyle}>{_buttons}</Row>) : null; } render() { return (<Form className={'o-com-archive ' + this.props.className} style={this.props.style} layout={this.props.layout} onSubmit={this.props.buttonProps.noButton && this.handleSubmit}> <Row gutter={24}> {this.getFields()} {this.props.limit && this.props.limit < this.props.options.length ? (<a className="o-com-archive_expand" onClick={this.toggle}> more <Icon type={this.state.expand ? 'up' : 'down'} /> </a>) : null} </Row> {this.getButtons()} </Form>); } } class ArchiveGroup extends React.PureComponent { static propTypes = { options: PropTypes.array, dataSource: PropTypes.object } static defaultProps = { options: [], dataSource: {} } render() { return (<div className="o-com-archive-group"> { this.props.options.map(item => { return (<div key={item.name} className="o-com-archive-group_box"> <h5>{item.title || item.name}</h5> <Divider /> <Archive {...item.attrs} {...this.props} options={item.items} dataSource={this.props.dataSource[item.name]} /> </div>); }) } </div>); } } export const Archive = Form.create({name: 'archive'})(IArchive); Archive.Group = ArchiveGroup;