动态菜单和动态路由的 antd pro

AdvancedForm.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. import React, { PureComponent } from 'react';
  2. import {
  3. Card,
  4. Button,
  5. Form,
  6. Icon,
  7. Col,
  8. Row,
  9. DatePicker,
  10. TimePicker,
  11. Input,
  12. Select,
  13. Popover,
  14. } from 'antd';
  15. import { connect } from 'dva';
  16. import FooterToolbar from 'components/FooterToolbar';
  17. import PageHeaderLayout from '../../layouts/PageHeaderLayout';
  18. import TableForm from './TableForm';
  19. import styles from './style.less';
  20. const { Option } = Select;
  21. const { RangePicker } = DatePicker;
  22. const fieldLabels = {
  23. name: '仓库名',
  24. url: '仓库域名',
  25. owner: '仓库管理员',
  26. approver: '审批人',
  27. dateRange: '生效日期',
  28. type: '仓库类型',
  29. name2: '任务名',
  30. url2: '任务描述',
  31. owner2: '执行人',
  32. approver2: '责任人',
  33. dateRange2: '生效日期',
  34. type2: '任务类型',
  35. };
  36. const tableData = [
  37. {
  38. key: '1',
  39. workId: '00001',
  40. name: 'John Brown',
  41. department: 'New York No. 1 Lake Park',
  42. },
  43. {
  44. key: '2',
  45. workId: '00002',
  46. name: 'Jim Green',
  47. department: 'London No. 1 Lake Park',
  48. },
  49. {
  50. key: '3',
  51. workId: '00003',
  52. name: 'Joe Black',
  53. department: 'Sidney No. 1 Lake Park',
  54. },
  55. ];
  56. class AdvancedForm extends PureComponent {
  57. state = {
  58. width: '100%',
  59. };
  60. componentDidMount() {
  61. window.addEventListener('resize', this.resizeFooterToolbar);
  62. }
  63. componentWillUnmount() {
  64. window.removeEventListener('resize', this.resizeFooterToolbar);
  65. }
  66. resizeFooterToolbar = () => {
  67. const sider = document.querySelectorAll('.ant-layout-sider')[0];
  68. const width = `calc(100% - ${sider.style.width})`;
  69. if (this.state.width !== width) {
  70. this.setState({ width });
  71. }
  72. };
  73. render() {
  74. const { form, dispatch, submitting } = this.props;
  75. const { getFieldDecorator, validateFieldsAndScroll, getFieldsError } = form;
  76. const validate = () => {
  77. validateFieldsAndScroll((error, values) => {
  78. if (!error) {
  79. // submit the values
  80. dispatch({
  81. type: 'form/submitAdvancedForm',
  82. payload: values,
  83. });
  84. }
  85. });
  86. };
  87. const errors = getFieldsError();
  88. const getErrorInfo = () => {
  89. const errorCount = Object.keys(errors).filter(key => errors[key]).length;
  90. if (!errors || errorCount === 0) {
  91. return null;
  92. }
  93. const scrollToField = fieldKey => {
  94. const labelNode = document.querySelector(`label[for="${fieldKey}"]`);
  95. if (labelNode) {
  96. labelNode.scrollIntoView(true);
  97. }
  98. };
  99. const errorList = Object.keys(errors).map(key => {
  100. if (!errors[key]) {
  101. return null;
  102. }
  103. return (
  104. <li key={key} className={styles.errorListItem} onClick={() => scrollToField(key)}>
  105. <Icon type="cross-circle-o" className={styles.errorIcon} />
  106. <div className={styles.errorMessage}>{errors[key][0]}</div>
  107. <div className={styles.errorField}>{fieldLabels[key]}</div>
  108. </li>
  109. );
  110. });
  111. return (
  112. <span className={styles.errorIcon}>
  113. <Popover
  114. title="表单校验信息"
  115. content={errorList}
  116. overlayClassName={styles.errorPopover}
  117. trigger="click"
  118. getPopupContainer={trigger => trigger.parentNode}
  119. >
  120. <Icon type="exclamation-circle" />
  121. </Popover>
  122. {errorCount}
  123. </span>
  124. );
  125. };
  126. return (
  127. <PageHeaderLayout
  128. title="高级表单"
  129. content="高级表单常见于一次性输入和提交大批量数据的场景。"
  130. wrapperClassName={styles.advancedForm}
  131. >
  132. <Card title="仓库管理" className={styles.card} bordered={false}>
  133. <Form layout="vertical" hideRequiredMark>
  134. <Row gutter={16}>
  135. <Col lg={6} md={12} sm={24}>
  136. <Form.Item label={fieldLabels.name}>
  137. {getFieldDecorator('name', {
  138. rules: [{ required: true, message: '请输入仓库名称' }],
  139. })(<Input placeholder="请输入仓库名称" />)}
  140. </Form.Item>
  141. </Col>
  142. <Col xl={{ span: 6, offset: 2 }} lg={{ span: 8 }} md={{ span: 12 }} sm={24}>
  143. <Form.Item label={fieldLabels.url}>
  144. {getFieldDecorator('url', {
  145. rules: [{ required: true, message: '请选择' }],
  146. })(
  147. <Input
  148. style={{ width: '100%' }}
  149. addonBefore="http://"
  150. addonAfter=".com"
  151. placeholder="请输入"
  152. />
  153. )}
  154. </Form.Item>
  155. </Col>
  156. <Col xl={{ span: 8, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
  157. <Form.Item label={fieldLabels.owner}>
  158. {getFieldDecorator('owner', {
  159. rules: [{ required: true, message: '请选择管理员' }],
  160. })(
  161. <Select placeholder="请选择管理员">
  162. <Option value="xiao">付晓晓</Option>
  163. <Option value="mao">周毛毛</Option>
  164. </Select>
  165. )}
  166. </Form.Item>
  167. </Col>
  168. </Row>
  169. <Row gutter={16}>
  170. <Col lg={6} md={12} sm={24}>
  171. <Form.Item label={fieldLabels.approver}>
  172. {getFieldDecorator('approver', {
  173. rules: [{ required: true, message: '请选择审批员' }],
  174. })(
  175. <Select placeholder="请选择审批员">
  176. <Option value="xiao">付晓晓</Option>
  177. <Option value="mao">周毛毛</Option>
  178. </Select>
  179. )}
  180. </Form.Item>
  181. </Col>
  182. <Col xl={{ span: 6, offset: 2 }} lg={{ span: 8 }} md={{ span: 12 }} sm={24}>
  183. <Form.Item label={fieldLabels.dateRange}>
  184. {getFieldDecorator('dateRange', {
  185. rules: [{ required: true, message: '请选择生效日期' }],
  186. })(
  187. <RangePicker placeholder={['开始日期', '结束日期']} style={{ width: '100%' }} />
  188. )}
  189. </Form.Item>
  190. </Col>
  191. <Col xl={{ span: 8, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
  192. <Form.Item label={fieldLabels.type}>
  193. {getFieldDecorator('type', {
  194. rules: [{ required: true, message: '请选择仓库类型' }],
  195. })(
  196. <Select placeholder="请选择仓库类型">
  197. <Option value="private">私密</Option>
  198. <Option value="public">公开</Option>
  199. </Select>
  200. )}
  201. </Form.Item>
  202. </Col>
  203. </Row>
  204. </Form>
  205. </Card>
  206. <Card title="任务管理" className={styles.card} bordered={false}>
  207. <Form layout="vertical" hideRequiredMark>
  208. <Row gutter={16}>
  209. <Col lg={6} md={12} sm={24}>
  210. <Form.Item label={fieldLabels.name2}>
  211. {getFieldDecorator('name2', {
  212. rules: [{ required: true, message: '请输入' }],
  213. })(<Input placeholder="请输入" />)}
  214. </Form.Item>
  215. </Col>
  216. <Col xl={{ span: 6, offset: 2 }} lg={{ span: 8 }} md={{ span: 12 }} sm={24}>
  217. <Form.Item label={fieldLabels.url2}>
  218. {getFieldDecorator('url2', {
  219. rules: [{ required: true, message: '请选择' }],
  220. })(<Input placeholder="请输入" />)}
  221. </Form.Item>
  222. </Col>
  223. <Col xl={{ span: 8, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
  224. <Form.Item label={fieldLabels.owner2}>
  225. {getFieldDecorator('owner2', {
  226. rules: [{ required: true, message: '请选择管理员' }],
  227. })(
  228. <Select placeholder="请选择管理员">
  229. <Option value="xiao">付晓晓</Option>
  230. <Option value="mao">周毛毛</Option>
  231. </Select>
  232. )}
  233. </Form.Item>
  234. </Col>
  235. </Row>
  236. <Row gutter={16}>
  237. <Col lg={6} md={12} sm={24}>
  238. <Form.Item label={fieldLabels.approver2}>
  239. {getFieldDecorator('approver2', {
  240. rules: [{ required: true, message: '请选择审批员' }],
  241. })(
  242. <Select placeholder="请选择审批员">
  243. <Option value="xiao">付晓晓</Option>
  244. <Option value="mao">周毛毛</Option>
  245. </Select>
  246. )}
  247. </Form.Item>
  248. </Col>
  249. <Col xl={{ span: 6, offset: 2 }} lg={{ span: 8 }} md={{ span: 12 }} sm={24}>
  250. <Form.Item label={fieldLabels.dateRange2}>
  251. {getFieldDecorator('dateRange2', {
  252. rules: [{ required: true, message: '请输入' }],
  253. })(
  254. <TimePicker
  255. placeholder="提醒时间"
  256. style={{ width: '100%' }}
  257. getPopupContainer={trigger => trigger.parentNode}
  258. />
  259. )}
  260. </Form.Item>
  261. </Col>
  262. <Col xl={{ span: 8, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
  263. <Form.Item label={fieldLabels.type2}>
  264. {getFieldDecorator('type2', {
  265. rules: [{ required: true, message: '请选择仓库类型' }],
  266. })(
  267. <Select placeholder="请选择仓库类型">
  268. <Option value="private">私密</Option>
  269. <Option value="public">公开</Option>
  270. </Select>
  271. )}
  272. </Form.Item>
  273. </Col>
  274. </Row>
  275. </Form>
  276. </Card>
  277. <Card title="成员管理" bordered={false}>
  278. {getFieldDecorator('members', {
  279. initialValue: tableData,
  280. })(<TableForm />)}
  281. </Card>
  282. <FooterToolbar style={{ width: this.state.width }}>
  283. {getErrorInfo()}
  284. <Button type="primary" onClick={validate} loading={submitting}>
  285. 提交
  286. </Button>
  287. </FooterToolbar>
  288. </PageHeaderLayout>
  289. );
  290. }
  291. }
  292. export default connect(({ global, loading }) => ({
  293. collapsed: global.collapsed,
  294. submitting: loading.effects['form/submitAdvancedForm'],
  295. }))(Form.create()(AdvancedForm));