CampusCreate.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /* eslint-disable no-trailing-spaces */
  2. import React, { PureComponent } from 'react';
  3. import pathToRegexp from 'path-to-regexp';
  4. import { message, Card, Modal, List, Form, Input, Button, Popover, Icon } from 'antd';
  5. import { connect } from 'dva';
  6. import { routerRedux } from 'dva/router';
  7. import Selector from '../../components/AXTableSelector/Selector';
  8. import AXCityCascader from '../../components/AXCityCascader';
  9. import FooterToolbar from '../../components/FooterToolbar';
  10. import PageHeaderLayout from '../../layouts/PageHeaderLayout';
  11. import {
  12. provinceCodeToName,
  13. provinceNameToCode,
  14. } from '../../utils/utils';
  15. import styles from './CampusCreate.less';
  16. const Message = message;
  17. const fieldLabels = {
  18. merchant: '所属商户',
  19. cityName: '所在城市',
  20. zoneName: '校区名称',
  21. contactName: '校区联系人',
  22. mobile: '联系电话',
  23. address: '收货地址',
  24. depositBank: '开户行',
  25. bankAccount: '银行账户',
  26. };
  27. const formItemLayout = {
  28. labelCol: {
  29. xs: { span: 24 },
  30. sm: { span: 7 },
  31. },
  32. wrapperCol: {
  33. xs: { span: 24 },
  34. sm: { span: 14 },
  35. md: { span: 11 },
  36. },
  37. };
  38. @Form.create()
  39. @connect(({ loading, merchant, campus }) => ({
  40. campus,
  41. merchant,
  42. submitting: loading.models.campus,
  43. loading: loading.models.merchant,
  44. }))
  45. export default class CampusCreatePage extends PureComponent {
  46. state = {
  47. merchantSelectorDestroy: true,
  48. };
  49. componentDidMount() {
  50. // 如果是编辑校区,加载校区详情
  51. const matchId = this.isEdit();
  52. if (matchId) {
  53. this.props.dispatch({
  54. type: 'campus/fetchCampusItem',
  55. payload: { id: matchId },
  56. });
  57. }
  58. }
  59. componentWillUnmount() {
  60. this.props.dispatch({
  61. type: 'campus/cleanState',
  62. payload: {},
  63. });
  64. }
  65. isEdit = () => {
  66. const { location } = this.props;
  67. const match = pathToRegexp('/campus/edit/:id').exec(location.pathname);
  68. if (match) {
  69. return match[1];
  70. }
  71. return false;
  72. };
  73. handleMerchantSelectorModalShow = () => {
  74. this.setState({
  75. merchantSelectorDestroy: false,
  76. });
  77. this.props.dispatch({
  78. type: 'merchant/fetchMerchantList',
  79. payload: {},
  80. });
  81. };
  82. handleMerchantSelectorFinish = (rows) => {
  83. this.setState({
  84. merchantSelectorDestroy: true,
  85. });
  86. if (!rows || !rows.length) {
  87. return;
  88. }
  89. const { id, name } = rows[0];
  90. this.props.dispatch({
  91. type: 'campus/fixCurrentItem',
  92. payload: {
  93. merchantId: id,
  94. merchantName: name,
  95. },
  96. });
  97. };
  98. handleMerchantSelectorCancel = () => {
  99. this.setState({
  100. merchantSelectorDestroy: true,
  101. });
  102. };
  103. handleMerchantSelectorChange = (params) => {
  104. this.props.dispatch({
  105. type: 'merchant/fetchMerchantList',
  106. payload: params,
  107. });
  108. };
  109. handlePageSubmit = () => {
  110. this.props.form.validateFieldsAndScroll((error, values) => {
  111. if (!error) {
  112. const { campus } = this.props;
  113. const { currentItem } = campus;
  114. const { merchantId } = currentItem;
  115. if (!merchantId) {
  116. Message.error('请选择该校区所属厂商');
  117. return;
  118. }
  119. const { cityName, ...restProps } = values;
  120. const [province, city] = cityName;
  121. restProps.provinceCode = provinceNameToCode(province);
  122. restProps.cityName = city;
  123. restProps.merchantId = merchantId;
  124. const matchId = this.isEdit();
  125. if (matchId) {
  126. restProps.id = matchId;
  127. this.props.dispatch({
  128. type: 'campus/updateCampusItem',
  129. payload: restProps,
  130. states: this.props.location.state,
  131. });
  132. } else {
  133. this.props.dispatch({
  134. type: 'campus/createCampusItem',
  135. payload: restProps,
  136. states: this.props.location.state,
  137. });
  138. }
  139. }
  140. });
  141. };
  142. handlePageBack = () => {
  143. this.props.dispatch(routerRedux.push({
  144. pathname: '/campus/list',
  145. state: this.props.location.state,
  146. }));
  147. };
  148. render() {
  149. const { merchantSelectorDestroy } = this.state;
  150. const { form, merchant, mLoading, campus, submitting } = this.props;
  151. const { getFieldDecorator, getFieldsError } = form;
  152. const { currentItem } = campus;
  153. const { merchantName } = currentItem;
  154. const renderCityName = () => {
  155. const { provinceCode, cityName } = currentItem;
  156. if (!provinceCode && !cityName) {
  157. return null;
  158. } else {
  159. return [
  160. provinceCodeToName(provinceCode),
  161. cityName,
  162. ];
  163. }
  164. };
  165. const errors = getFieldsError();
  166. const getErrorInfo = () => {
  167. const errorCount = Object.keys(errors).filter(key => errors[key]).length;
  168. if (!errors || errorCount === 0) {
  169. return null;
  170. }
  171. const scrollToField = (fieldKey) => {
  172. const labelNode = document.querySelector(`label[for="${fieldKey}"]`);
  173. if (labelNode) {
  174. labelNode.scrollIntoView(true);
  175. }
  176. };
  177. const errorList = Object.keys(errors).map((key) => {
  178. if (!errors[key]) {
  179. return null;
  180. }
  181. return (
  182. <li key={key} className={styles.errorListItem} onClick={() => scrollToField(key)}>
  183. <Icon type="cross-circle-o" className={styles.errorIcon} />
  184. <div className={styles.errorMessage}>{errors[key][0]}</div>
  185. <div className={styles.errorField}>{fieldLabels[key]}</div>
  186. </li>
  187. );
  188. });
  189. return (
  190. <span className={styles.errorIcon}>
  191. <Popover
  192. title="表单校验信息"
  193. content={errorList}
  194. overlayClassName={styles.errorPopover}
  195. trigger="click"
  196. getPopupContainer={trigger => trigger.parentNode}
  197. >
  198. <Icon type="exclamation-circle" />
  199. </Popover>
  200. {errorCount}
  201. </span>
  202. );
  203. };
  204. const getMerchantModal = () => {
  205. return (
  206. <Modal
  207. visible
  208. width={1100}
  209. footer={null}
  210. title="厂商列表"
  211. maskClosable={false}
  212. onCancel={this.handleMerchantSelectorCancel}
  213. >
  214. <Selector
  215. multiple={false}
  216. loading={mLoading}
  217. selectorName="Merchant"
  218. list={merchant.list}
  219. pageNo={merchant.pageNo}
  220. pageSize={merchant.pageSize}
  221. totalSize={merchant.totalSize}
  222. onCancel={this.handleMerchantSelectorCancel}
  223. onChange={this.handleMerchantSelectorChange}
  224. onFinish={this.handleMerchantSelectorFinish}
  225. />
  226. </Modal>
  227. );
  228. };
  229. return (
  230. <PageHeaderLayout>
  231. <Card style={{ marginBottom: 70 }}>
  232. <Form>
  233. <Form.Item
  234. {...formItemLayout}
  235. label={!this.isEdit() ? <Button size="small" type="primary" onClick={this.handleMerchantSelectorModalShow}>所属厂商</Button> : '所属厂商'}
  236. >
  237. <List
  238. bordered
  239. size="small"
  240. dataSource={[
  241. `${merchantName || '请选择'}`,
  242. ]}
  243. renderItem={item => <List.Item>{item}</List.Item>}
  244. />
  245. </Form.Item>
  246. <Form.Item label={fieldLabels.cityName} {...formItemLayout}>
  247. {getFieldDecorator('cityName', {
  248. rules: [{ required: true, message: '请选择校区地址!' }],
  249. initialValue: renderCityName(),
  250. })(
  251. <AXCityCascader />
  252. )}
  253. </Form.Item>
  254. <Form.Item label={fieldLabels.zoneName} {...formItemLayout}>
  255. {getFieldDecorator('zoneName', {
  256. rules: [{ required: true, message: '校区名不能为空!' }],
  257. initialValue: currentItem.zoneName,
  258. })(
  259. <Input placeholder="请输入" />
  260. )}
  261. </Form.Item>
  262. <Form.Item label={fieldLabels.contactName} {...formItemLayout}>
  263. {getFieldDecorator('contactName', {
  264. rules: [{ required: true, message: '联系人不能为空!' }],
  265. initialValue: currentItem.contactName,
  266. })(
  267. <Input placeholder="请输入" />
  268. )}
  269. </Form.Item>
  270. <Form.Item label={fieldLabels.mobile} {...formItemLayout}>
  271. {getFieldDecorator('mobile', {
  272. rules: [
  273. {
  274. required: true, message: '联系电话不能为空!',
  275. }, {
  276. pattern: /^[1][34578][0-9]{9}$/g, message: '请输入11位有效手机号!',
  277. }],
  278. initialValue: currentItem.mobile,
  279. })(
  280. <Input placeholder="请输入" />
  281. )}
  282. </Form.Item>
  283. <Form.Item label={fieldLabels.depositBank} {...formItemLayout}>
  284. {getFieldDecorator('depositBank', {
  285. initialValue: currentItem.depositBank,
  286. })(
  287. <Input placeholder="请输入" />
  288. )}
  289. </Form.Item>
  290. <Form.Item label={fieldLabels.bankAccount} {...formItemLayout}>
  291. {getFieldDecorator('bankAccount', {
  292. initialValue: currentItem.bankAccount,
  293. })(
  294. <Input placeholder="请输入" />
  295. )}
  296. </Form.Item>
  297. <Form.Item label={fieldLabels.address} {...formItemLayout}>
  298. {getFieldDecorator('address', {
  299. initialValue: currentItem.address,
  300. })(
  301. <Input placeholder="请输入" />
  302. )}
  303. </Form.Item>
  304. </Form>
  305. {!merchantSelectorDestroy && getMerchantModal()}
  306. </Card>
  307. <FooterToolbar style={{ width: '100%' }}>
  308. {getErrorInfo()}
  309. <Button onClick={this.handlePageBack} style={{ marginRight: 10 }}>
  310. 取消
  311. </Button>
  312. <Button type="primary" onClick={this.handlePageSubmit} loading={submitting}>
  313. 提交
  314. </Button>
  315. </FooterToolbar>
  316. </PageHeaderLayout>
  317. );
  318. }
  319. }