index.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import React, { Component } from 'react';
  2. import moment from 'moment';
  3. import { Form, Button, Switch, DatePicker, Input, InputNumber, Modal, Alert, Cascader } from 'antd';
  4. import Select from '../../components/Select';
  5. import Multiple from '../../components/Multiple';
  6. import Radio from '../../components/Radio';
  7. import TreeSelect from '../../components/TreeSelect';
  8. import FileUpload from '../../components/FileUpload';
  9. import './index.less';
  10. const { TextArea } = Input;
  11. class FormLayout extends Component {
  12. constructor(props) {
  13. super(props);
  14. this.state = { show: !!props.modal, loading: false, err: '' };
  15. }
  16. onConfirm() {
  17. this.props.form.validateFields((err, fieldsValue) => {
  18. if (err) {
  19. return;
  20. }
  21. if (this.props.onConfirm && this.props.modal) {
  22. this.setState({ loading: true });
  23. this.props
  24. .onConfirm(fieldsValue)
  25. .then(() => {
  26. this.setState({ loading: false });
  27. this.onCancel();
  28. })
  29. .catch(e => {
  30. this.setState({ loading: false, err: e.message });
  31. });
  32. } else {
  33. this.onCancel();
  34. }
  35. });
  36. }
  37. onCancel() {
  38. if (this.props.modal) this.setState({ show: false });
  39. if (this.props.onCancel) this.props.onCancel();
  40. }
  41. getItem(item) {
  42. switch (item.type) {
  43. case 'tree':
  44. return (
  45. <TreeSelect
  46. {...item}
  47. className={item.class}
  48. disabled={!!item.disabled}
  49. placeholder={item.placeholder}
  50. isNode={item.isNode}
  51. treeDefaultExpandAll
  52. treeData={item.tree}
  53. loadData={item.loadData}
  54. initData={item.initData}
  55. ignore={item.ignore}
  56. />
  57. );
  58. case 'radio':
  59. return <Radio {...item} className={item.class} select={item.select} disabled={!!item.disabled} />;
  60. case 'select':
  61. return (
  62. <Select
  63. {...item}
  64. className={item.class}
  65. select={item.select}
  66. placeholder={item.placeholder}
  67. disabled={!!item.disabled}
  68. />
  69. );
  70. case 'multiple':
  71. return (
  72. <Multiple
  73. {...item}
  74. className={item.class}
  75. select={item.select}
  76. placeholder={item.placeholder}
  77. disabled={!!item.disabled}
  78. />
  79. );
  80. case 'cascader':
  81. return <Cascader {...item} className={item.class} options={item.select} placeholder={item.placeholder} />;
  82. case 'render':
  83. return item.render(item, this.props.data, this.props.form);
  84. case 'textarea':
  85. return <TextArea {...item} autosize className={item.class} placeholder={item.placeholder} disabled={!!item.disabled} />;
  86. case 'password':
  87. case 'input':
  88. return (
  89. <Input
  90. {...item}
  91. className={item.class}
  92. placeholder={item.placeholder}
  93. readOnly={!!item.readOnly}
  94. disabled={!!item.disabled}
  95. />
  96. );
  97. case 'number':
  98. return (
  99. <InputNumber
  100. {...item}
  101. className={item.class}
  102. placeholder={item.placeholder}
  103. readOnly={!!item.readOnly}
  104. disabled={!!item.disabled}
  105. />
  106. );
  107. case 'switch':
  108. return <Switch {...item} className={item.class} disabled={!!item.disabled} />;
  109. case 'date':
  110. return <DatePicker {...item} className={item.class} placeholder={item.placeholder} disabled={!!item.disabled} />;
  111. case 'daterange':
  112. return <DatePicker.RangePicker {...item} className={item.class} />;
  113. case 'hidden':
  114. return <Input type="hidden" />;
  115. case 'image':
  116. case 'logo':
  117. case 'file':
  118. return (
  119. <FileUpload
  120. {...item}
  121. title={item.name}
  122. onEnd={url => {
  123. this.props.form.setFieldsValue({ [item.key]: url });
  124. }}
  125. onError={err => {
  126. this.props.form.setFields({ [item.key]: { value: '', errors: [err] } });
  127. }}
  128. />
  129. );
  130. default:
  131. return <div />;
  132. }
  133. }
  134. formatData(data, item) {
  135. switch (item.type) {
  136. case 'date':
  137. return moment(data[item.key]);
  138. default:
  139. return data[item.key];
  140. }
  141. }
  142. getForm() {
  143. const {
  144. modal,
  145. itemList = [],
  146. confirmText = '确定',
  147. cancelText = '取消',
  148. data = {},
  149. layoutCol = { labelCol: { span: 4 }, wrapperCol: { span: 20 } },
  150. } = this.props;
  151. const { getFieldDecorator } = this.props.form;
  152. return (
  153. <Form>
  154. {itemList.map((item, index) => {
  155. if (item.hidden) return '';
  156. const defaultOption = { rules: [] };
  157. const option = item.option ? Object.assign(defaultOption, item.option) : defaultOption;
  158. if (data && data[item.key]) {
  159. option.initialValue = this.formatData(data, item);
  160. }
  161. if (item.required) {
  162. option.rules.push({ required: true, message: item.placeholder });
  163. }
  164. if (item.type === 'hidden') {
  165. return <div>{getFieldDecorator(item.key, option)(this.getItem(item, option))}</div>;
  166. }
  167. return (
  168. <Form.Item {...layoutCol} key={index} label={item.name}>
  169. {getFieldDecorator(item.key, option)(this.getItem(item, option))}
  170. </Form.Item>
  171. );
  172. })}
  173. {!modal && (
  174. <Form.Item wrapperCol={{ offset: 6 }}>
  175. <Button type="primary" onClick={() => this.onConfirm()} style={{ marginRight: 20 }}>
  176. {confirmText}
  177. </Button>
  178. <Button onClick={() => this.onCancel()}>{cancelText}</Button>
  179. </Form.Item>
  180. )}
  181. </Form>
  182. );
  183. }
  184. render() {
  185. const { modal, title, confirmText = '确定', cancelText = '取消' } = this.props;
  186. const { show, loading, err } = this.state;
  187. return modal ? (
  188. <Modal
  189. title={title}
  190. visible={show}
  191. className="form-layout"
  192. okText={confirmText}
  193. cancelText={cancelText}
  194. confirmLoading={loading}
  195. onOk={() => this.onConfirm()}
  196. onCancel={() => this.onCancel()}
  197. >
  198. {err && <Alert type="error" showIcon message={err} closable onClose={() => this.setState({ err: '' })} />}
  199. {this.getForm()}
  200. </Modal>
  201. ) : (<div className="form-layout">{this.getForm()}</div>);
  202. }
  203. }
  204. export default Form.create()(FormLayout);