UNPKG

alaska-field-image

Version:

Alaska image field

201 lines (184 loc) 5.15 kB
// @flow import React from 'react'; import PropTypes from 'prop-types'; import _ from 'lodash'; import shallowEqualWithout from 'shallow-equal-without'; import { api } from 'alaska-admin-view'; type State = { max: number, errorText: string, multi: any }; export default class ImageFieldView extends React.Component<Alaska$view$Field$View$Props, State> { static contextTypes = { settings: PropTypes.object, t: PropTypes.func }; imageInput: any; constructor(props: Alaska$view$Field$View$Props) { super(props); this.state = { max: props.field.max || 1000, errorText: '', multi: '' }; if (!props.field.multi) { this.state.max = 1; } } componentWillReceiveProps(nextProps: Alaska$view$Field$View$Props) { let newState = {}; if (nextProps.errorText !== undefined) { newState.errorText = nextProps.errorText; this.setState(newState); } } shouldComponentUpdate(props: Alaska$view$Field$View$Props, state: State) { return !shallowEqualWithout(props, this.props, 'record', 'onChange', 'model') || !shallowEqualWithout(state, this.state); } handleAddImage = () => { const { t } = this.context; let { model, field, record, value } = this.props; let { multi } = field; if (value) { if (!multi) { value = [value]; } else { value = value.concat(); } } else { value = []; } let id = '_new'; let { serviceId, modelName } = model || { serviceId: 'alaska-user', modelName: 'User' }; if (record && record._id) { id = record._id; } let nextState = { errorText: '' }; _.forEach(this.imageInput.files, (file) => { if (value.length >= this.state.max || !file) return; let matchs = file.name.match(/\.(\w+)$/); let temp: boolean = (field.allowed || ['jpg', 'png']).indexOf(matchs[1].replace('jpeg', 'jpg').toLowerCase()) < 0; if (!matchs || !matchs[1] || temp) { nextState.errorText = t('Invalid image format'); return; } api.upload('/api/upload', { params: { _service: serviceId, _model: modelName, _path: field.path || 'avatar', }, body: { file, id } }).then((res) => { value = value.concat(res); if (this.props.onChange) { this.props.onChange(multi ? value : res); } }, (error) => { this.setState({ errorText: error.message }); }); }); this.setState(nextState); }; handleRemoveItem(item: any) { let value = null; if (this.props.field.multi) { value = []; _.forEach(this.props.value, (i) => { if (i !== item) { // $Flow 我们知道此处value 为数组 value.push(i); } }); } if (this.props.onChange) { this.props.onChange(value); } } render() { let { className, field, value, disabled } = this.props; let { errorText, max } = this.state; if (!field.multi) { value = value ? [value] : []; } let items = []; let readonly = disabled || field.fixed; // $Flow 和lodash的flow不匹配 _.forEach(value, (item, index) => { items.push(( <div key={index} className="image-field-item"> <img alt="" src={item.thumbUrl} /> { readonly ? null : ( <button className="btn btn-link btn-block" disabled={disabled} onClick={() => this.handleRemoveItem(item)} >删除</button> ) } </div> )); }); if (items.length < max) { //还未超出 if (!readonly) { items.push(( <div className="image-field-item image-field-add" key="add"> <i className="fa fa-plus-square-o" /> <input ref={(r) => { this.imageInput = r; }} multiple={this.state.multi} accept="image/png;image/jpg;" type="file" onChange={this.handleAddImage} /> </div> )); } } if (!items.length && readonly) { items.push(( <div className="image-field-item image-field-add" key="add"> <i className="fa fa-picture-o" /> </div> )); } let { help } = field; className += ' image-field'; if (errorText) { className += ' has-error'; help = errorText; } let helpElement = help ? <p className="help-block">{help}</p> : null; let label = field.nolabel ? '' : field.label; if (field.horizontal) { return ( <div className={className}> <label className="col-sm-2 control-label">{label}</label> <div className="col-sm-10"> {items} {helpElement} </div> </div> ); } return ( <div className={className}> {label ? (<label className="control-label">{label}</label>) : null} <div>{items}</div> {helpElement} </div> ); } }