diff --git a/.umirc.js b/.umirc.js index 25c97ae..55205b5 100644 --- a/.umirc.js +++ b/.umirc.js @@ -72,7 +72,7 @@ export default { antd: { name: 'antd', priority: 20, - test: /[\\/]node_modules[\\/](antd|@ant-design\/icons|@ant-design\/compatible|ant-design-pro)[\\/]/, + test: /[\\/]node_modules[\\/](antd|@ant-design\/icons|@ant-design\/compatible)[\\/]/, }, echarts: { name: 'echarts', diff --git a/docs/change-log.md b/docs/change-log.md index 003adf1..3465321 100644 --- a/docs/change-log.md +++ b/docs/change-log.md @@ -28,7 +28,7 @@ - Support internationalization, extract source fields from source code, load language packs on demand, and automatically translate online. -- Support for the introduction of `ant-design-pro` components, `lodash` functions on demand. +- Support for the introduction `lodash` functions on demand.    - Support multiple layouts, which rules can be used according to the rules. diff --git a/docs/zh-cn/change-log.md b/docs/zh-cn/change-log.md index e3ef954..54b0ec6 100644 --- a/docs/zh-cn/change-log.md +++ b/docs/zh-cn/change-log.md @@ -28,7 +28,7 @@ - 支持国际化,源码中抽离翻译字段,按需加载语言包,自动在线翻译。 -- 支持按需引入 `ant-design-pro` 组件、`lodash` 函数。 +- 支持按需引入 `lodash` 函数。 - 支持多布局,可根据规则规定哪些路由使用哪种布局。 diff --git a/package.json b/package.json index fcab4c5..6b4d28a 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,6 @@ "@ant-design/compatible": "^1.0.0", "@ant-design/icons": "^4.0.0", "@lingui/react": "^2.8.0", - "ant-design-pro": "^2.3.0", "antd": "^4.0.0", "axios": "^0.19.0", "classnames": "^2.2.6", @@ -39,14 +38,14 @@ "store": "^2.0.0" }, "devDependencies": { - "@lingui/babel-preset-react": "^2.8.2", - "@lingui/cli": "^2.8.2", - "@lingui/loader": "^2.8.2", + "@lingui/babel-preset-react": "^2.9.0", + "@lingui/cli": "^2.9.0", + "@lingui/loader": "^2.9.0", "@umijs/preset-react": "^1.4.0", "babel-eslint": "^10.0.1", "babel-plugin-dev-expression": "^0.2.1", "babel-plugin-module-resolver": "^4.0.0", - "cross-env": "^7.0.0", + "cross-env": "^6.0.0", "eslint": "^6.8.0", "eslint-config-react-app": "^5.0.0", "eslint-plugin-flowtype": "^4.6.0", diff --git a/src/components/Ellipsis/index.d.ts b/src/components/Ellipsis/index.d.ts new file mode 100644 index 0000000..075fa78 --- /dev/null +++ b/src/components/Ellipsis/index.d.ts @@ -0,0 +1,21 @@ +import React from 'react'; +import { TooltipProps } from 'antd/lib/tooltip'; + +export interface EllipsisTooltipProps extends TooltipProps { + title?: undefined; + overlayStyle?: undefined; +} + +export interface EllipsisProps { + tooltip?: boolean | EllipsisTooltipProps; + length?: number; + lines?: number; + style?: React.CSSProperties; + className?: string; + fullWidthRecognition?: boolean; +} + +export function getStrFullLength(str: string): number; +export function cutStrByFullLength(str: string, maxLength: number): string; + +export default class Ellipsis extends React.Component {} diff --git a/src/components/Ellipsis/index.js b/src/components/Ellipsis/index.js new file mode 100644 index 0000000..de700b7 --- /dev/null +++ b/src/components/Ellipsis/index.js @@ -0,0 +1,270 @@ +import React, { Component } from 'react'; +import { Tooltip } from 'antd'; +import classNames from 'classnames'; +import styles from './index.less'; + +/* eslint react/no-did-mount-set-state: 0 */ +/* eslint no-param-reassign: 0 */ + +const isSupportLineClamp = document.body.style.webkitLineClamp !== undefined; + +const TooltipOverlayStyle = { + overflowWrap: 'break-word', + wordWrap: 'break-word', +}; + +export const getStrFullLength = (str = '') => + str.split('').reduce((pre, cur) => { + const charCode = cur.charCodeAt(0); + if (charCode >= 0 && charCode <= 128) { + return pre + 1; + } + return pre + 2; + }, 0); + +export const cutStrByFullLength = (str = '', maxLength) => { + let showLength = 0; + return str.split('').reduce((pre, cur) => { + const charCode = cur.charCodeAt(0); + if (charCode >= 0 && charCode <= 128) { + showLength += 1; + } else { + showLength += 2; + } + if (showLength <= maxLength) { + return pre + cur; + } + return pre; + }, ''); +}; + +const getTooltip = ({ tooltip, overlayStyle, title, children }) => { + if (tooltip) { + const props = tooltip === true ? { overlayStyle, title } : { ...tooltip, overlayStyle, title }; + return {children}; + } + return children; +}; + +const EllipsisText = ({ text, length, tooltip, fullWidthRecognition, ...other }) => { + if (typeof text !== 'string') { + throw new Error('Ellipsis children must be string.'); + } + const textLength = fullWidthRecognition ? getStrFullLength(text) : text.length; + if (textLength <= length || length < 0) { + return {text}; + } + const tail = '...'; + let displayText; + if (length - tail.length <= 0) { + displayText = ''; + } else { + displayText = fullWidthRecognition ? cutStrByFullLength(text, length) : text.slice(0, length); + } + + const spanAttrs = tooltip ? {} : { ...other }; + return getTooltip({ + tooltip, + overlayStyle: TooltipOverlayStyle, + title: text, + children: ( + + {displayText} + {tail} + + ), + }); +}; + +export default class Ellipsis extends Component { + state = { + text: '', + targetCount: 0, + }; + + componentDidMount() { + if (this.node) { + this.computeLine(); + } + } + + componentDidUpdate(perProps) { + const { lines } = this.props; + if (lines !== perProps.lines) { + this.computeLine(); + } + } + + computeLine = () => { + const { lines } = this.props; + if (lines && !isSupportLineClamp) { + const text = this.shadowChildren.innerText || this.shadowChildren.textContent; + const lineHeight = parseInt(getComputedStyle(this.root).lineHeight, 10); + const targetHeight = lines * lineHeight; + this.content.style.height = `${targetHeight}px`; + const totalHeight = this.shadowChildren.offsetHeight; + const shadowNode = this.shadow.firstChild; + + if (totalHeight <= targetHeight) { + this.setState({ + text, + targetCount: text.length, + }); + return; + } + + // bisection + const len = text.length; + const mid = Math.ceil(len / 2); + + const count = this.bisection(targetHeight, mid, 0, len, text, shadowNode); + + this.setState({ + text, + targetCount: count, + }); + } + }; + + bisection = (th, m, b, e, text, shadowNode) => { + const suffix = '...'; + let mid = m; + let end = e; + let begin = b; + shadowNode.innerHTML = text.substring(0, mid) + suffix; + let sh = shadowNode.offsetHeight; + + if (sh <= th) { + shadowNode.innerHTML = text.substring(0, mid + 1) + suffix; + sh = shadowNode.offsetHeight; + if (sh > th || mid === begin) { + return mid; + } + begin = mid; + if (end - begin === 1) { + mid = 1 + begin; + } else { + mid = Math.floor((end - begin) / 2) + begin; + } + return this.bisection(th, mid, begin, end, text, shadowNode); + } + if (mid - 1 < 0) { + return mid; + } + shadowNode.innerHTML = text.substring(0, mid - 1) + suffix; + sh = shadowNode.offsetHeight; + if (sh <= th) { + return mid - 1; + } + end = mid; + mid = Math.floor((end - begin) / 2) + begin; + return this.bisection(th, mid, begin, end, text, shadowNode); + }; + + handleRoot = n => { + this.root = n; + }; + + handleContent = n => { + this.content = n; + }; + + handleNode = n => { + this.node = n; + }; + + handleShadow = n => { + this.shadow = n; + }; + + handleShadowChildren = n => { + this.shadowChildren = n; + }; + + render() { + const { text, targetCount } = this.state; + const { + children, + lines, + length, + className, + tooltip, + fullWidthRecognition, + ...restProps + } = this.props; + + const cls = classNames(styles.ellipsis, className, { + [styles.lines]: lines && !isSupportLineClamp, + [styles.lineClamp]: lines && isSupportLineClamp, + }); + + if (!lines && !length) { + return ( + + {children} + + ); + } + + // length + if (!lines) { + return ( + + ); + } + + const id = `antd-pro-ellipsis-${`${new Date().getTime()}${Math.floor(Math.random() * 100)}`}`; + + // support document.body.style.webkitLineClamp + if (isSupportLineClamp) { + const style = `#${id}{-webkit-line-clamp:${lines};-webkit-box-orient: vertical;}`; + + const node = ( +
+ + {children} +
+ ); + + return getTooltip({ + tooltip, + overlayStyle: TooltipOverlayStyle, + title: children, + children: node, + }); + } + + const childNode = ( + + {targetCount > 0 && text.substring(0, targetCount)} + {targetCount > 0 && targetCount < text.length && '...'} + + ); + + return ( +
+
+ {getTooltip({ + tooltip, + overlayStyle: TooltipOverlayStyle, + title: text, + children: childNode, + })} +
+ {children} +
+
+ {text} +
+
+
+ ); + } +} diff --git a/src/components/Ellipsis/index.less b/src/components/Ellipsis/index.less new file mode 100644 index 0000000..3c0360c --- /dev/null +++ b/src/components/Ellipsis/index.less @@ -0,0 +1,24 @@ +.ellipsis { + display: inline-block; + width: 100%; + overflow: hidden; + word-break: break-all; +} + +.lines { + position: relative; + .shadow { + position: absolute; + z-index: -999; + display: block; + color: transparent; + opacity: 0; + } +} + +.lineClamp { + position: relative; + display: -webkit-box; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/src/components/Ellipsis/index.md b/src/components/Ellipsis/index.md new file mode 100644 index 0000000..1875b17 --- /dev/null +++ b/src/components/Ellipsis/index.md @@ -0,0 +1,17 @@ +--- +title: Ellipsis +subtitle: 文本自动省略号 +cols: 1 +order: 10 +--- + +文本过长自动处理省略号,支持按照文本长度和最大行数两种方式截取。 + +## API + +| 参数 | 说明 | 类型 | 默认值 | +| -------------------- | ------------------------------------------------ | ------- | ------ | +| tooltip | 移动到文本展示完整内容的提示 | boolean | - | +| length | 在按照长度截取下的文本最大字符数,超过则截取省略 | number | - | +| lines | 在按照行数截取下最大的行数,超过则截取省略 | number | `1` | +| fullWidthRecognition | 是否将全角字符的长度视为 2 来计算字符串长度 | boolean | - | diff --git a/src/components/Ellipsis/index.test.js b/src/components/Ellipsis/index.test.js new file mode 100644 index 0000000..4d057b2 --- /dev/null +++ b/src/components/Ellipsis/index.test.js @@ -0,0 +1,13 @@ +import { getStrFullLength, cutStrByFullLength } from './index'; + +describe('test calculateShowLength', () => { + it('get full length', () => { + expect(getStrFullLength('一二,a,')).toEqual(8); + }); + it('cut str by full length', () => { + expect(cutStrByFullLength('一二,a,', 7)).toEqual('一二,a'); + }); + it('cut str when length small', () => { + expect(cutStrByFullLength('一22三', 5)).toEqual('一22'); + }); +}); diff --git a/src/components/GlobalFooter/index.d.ts b/src/components/GlobalFooter/index.d.ts new file mode 100644 index 0000000..efde77d --- /dev/null +++ b/src/components/GlobalFooter/index.d.ts @@ -0,0 +1,14 @@ +import React from 'react'; +export interface GlobalFooterProps { + links?: Array<{ + key?: string; + title: React.ReactNode; + href: string; + blankTarget?: boolean; + }>; + copyright?: React.ReactNode; + style?: React.CSSProperties; + className?: string; +} + +export default class GlobalFooter extends React.Component {} diff --git a/src/components/GlobalFooter/index.js b/src/components/GlobalFooter/index.js new file mode 100644 index 0000000..1c2fb74 --- /dev/null +++ b/src/components/GlobalFooter/index.js @@ -0,0 +1,28 @@ +import React from 'react'; +import classNames from 'classnames'; +import styles from './index.less'; + +const GlobalFooter = ({ className, links, copyright }) => { + const clsString = classNames(styles.globalFooter, className); + return ( +
+ {links && ( +
+ {links.map(link => ( + + {link.title} + + ))} +
+ )} + {copyright &&
{copyright}
} +
+ ); +}; + +export default GlobalFooter; diff --git a/src/components/GlobalFooter/index.less b/src/components/GlobalFooter/index.less new file mode 100644 index 0000000..e4b3dfd --- /dev/null +++ b/src/components/GlobalFooter/index.less @@ -0,0 +1,29 @@ +@import '~antd/lib/style/themes/default.less'; + +.globalFooter { + margin: 48px 0 24px 0; + padding: 0 16px; + text-align: center; + + .links { + margin-bottom: 8px; + + a { + color: @text-color-secondary; + transition: all 0.3s; + + &:not(:last-child) { + margin-right: 40px; + } + + &:hover { + color: @text-color; + } + } + } + + .copyright { + color: @text-color-secondary; + font-size: @font-size-base; + } +} diff --git a/src/components/GlobalFooter/index.md b/src/components/GlobalFooter/index.md new file mode 100644 index 0000000..5d6058f --- /dev/null +++ b/src/components/GlobalFooter/index.md @@ -0,0 +1,15 @@ +--- +title: GlobalFooter +subtitle: 全局页脚 +cols: 1 +order: 7 +--- + +页脚属于全局导航的一部分,作为对顶部导航的补充,通过传递数据控制展示内容。 + +## API + +| 参数 | 说明 | 类型 | 默认值 | +| --------- | -------- | ---------------------------------------------------------------- | ------ | +| links | 链接数据 | array<{ title: ReactNode, href: string, blankTarget?: boolean }> | - | +| copyright | 版权信息 | ReactNode | - | diff --git a/src/components/Layout/Header.js b/src/components/Layout/Header.js index 6bf0216..4990881 100644 --- a/src/components/Layout/Header.js +++ b/src/components/Layout/Header.js @@ -1,7 +1,7 @@ import React, { PureComponent, Fragment } from 'react' import PropTypes from 'prop-types' import { Menu, Layout, Avatar, Popover, Badge, List } from 'antd' -import { Ellipsis } from 'ant-design-pro' +import { Ellipsis } from 'components' import { Icon as LegacyIcon } from '@ant-design/compatible' import { BellOutlined, RightOutlined } from '@ant-design/icons' import { Trans, withI18n } from '@lingui/react' diff --git a/src/components/index.js b/src/components/index.js index 66ad69b..d3d3750 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -3,7 +3,9 @@ import FilterItem from './FilterItem' import DropOption from './DropOption' import Loader from './Loader' import ScrollBar from './ScrollBar' +import GlobalFooter from './GlobalFooter' +import Ellipsis from './Ellipsis' import * as MyLayout from './Layout/index.js' import Page from './Page' -export { MyLayout, Editor, FilterItem, DropOption, Loader, Page, ScrollBar } +export { MyLayout, Editor, GlobalFooter, Ellipsis, FilterItem, DropOption, Loader, Page, ScrollBar } diff --git a/src/layouts/PrimaryLayout.js b/src/layouts/PrimaryLayout.js index 01b665a..5000e35 100644 --- a/src/layouts/PrimaryLayout.js +++ b/src/layouts/PrimaryLayout.js @@ -4,9 +4,8 @@ import React, { PureComponent, Fragment } from 'react' import PropTypes from 'prop-types' import { withRouter } from 'umi' import { connect } from 'dva' -import { MyLayout } from 'components' +import { MyLayout, GlobalFooter } from 'components' import { BackTop, Layout, Drawer } from 'antd' -import { GlobalFooter } from 'ant-design-pro' import { enquireScreen, unenquireScreen } from 'enquire-js' const { pathToRegexp } = require("path-to-regexp") import { config, getLocale } from 'utils' diff --git a/src/layouts/index.js b/src/layouts/index.js index e02e9dd..20974cd 100644 --- a/src/layouts/index.js +++ b/src/layouts/index.js @@ -3,6 +3,7 @@ import { withRouter } from 'umi' import { ConfigProvider } from 'antd' import { I18nProvider } from '@lingui/react' import { getLocale } from 'utils' +const { i18n } = require('../../src/utils/config') import zh_CN from 'antd/lib/locale-provider/zh_CN' import en_US from 'antd/lib/locale-provider/en_US' import pt_BR from 'antd/lib/locale-provider/pt_BR' @@ -14,6 +15,7 @@ const languages = { en: en_US, 'pt-br': pt_BR, } +const { defaultLanguage } = i18n @withRouter class Layout extends Component { @@ -59,10 +61,10 @@ class Layout extends Component { } render() { - const { location, children } = this.props + const { children } = this.props const { catalogs } = this.state - let language = langFromPath(location.pathname) + let language = getLocale() // If the language pack is not loaded or is loading, use the default language if (!catalogs[language]) language = defaultLanguage diff --git a/src/pages/login/index.js b/src/pages/login/index.js index 74c9c53..ded757c 100644 --- a/src/pages/login/index.js +++ b/src/pages/login/index.js @@ -1,10 +1,8 @@ import React, { PureComponent, Fragment } from 'react' import PropTypes from 'prop-types' import { connect } from 'dva' -import { Button, Row, Input } from 'antd' -import { GlobalFooter } from 'ant-design-pro' -import { Form } from '@ant-design/compatible' -import '@ant-design/compatible/assets/index.css' +import { Button, Row, Input, Form } from 'antd' +import { GlobalFooter } from 'components' import { GithubOutlined } from '@ant-design/icons' import { Trans, withI18n } from '@lingui/react' import { setLocale } from 'utils' @@ -12,13 +10,12 @@ import config from 'utils/config' import styles from './index.less' const FormItem = Form.Item +const [form] = Form.useForm(); @withI18n() -@connect(({ loading }) => ({ loading })) -@Form.create() +@connect(({ loading, dispatch }) => ({ loading, dispatch })) class Login extends PureComponent { handleOk = () => { - const { dispatch, form } = this.props const { validateFieldsAndScroll } = form validateFieldsAndScroll((errors, values) => { if (errors) { @@ -29,8 +26,7 @@ class Login extends PureComponent { } render() { - const { loading, form, i18n } = this.props - const { getFieldDecorator } = form + const { loading, i18n } = this.props let footerLinks = [ { @@ -59,35 +55,21 @@ class Login extends PureComponent { logo {config.siteName} -
- - {getFieldDecorator('username', { - rules: [ - { - required: true, - }, - ], - })( + + - )} - - {getFieldDecorator('password', { - rules: [ - { - required: true, - }, - ], - })( + - )}

- + Username :guest @@ -108,7 +90,7 @@ class Login extends PureComponent {

- +
diff --git a/src/pages/post/components/List.js b/src/pages/post/components/List.js index 43bfeae..ed0f882 100644 --- a/src/pages/post/components/List.js +++ b/src/pages/post/components/List.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react' import { Table, Avatar } from 'antd' import { withI18n } from '@lingui/react' -import { Ellipsis } from 'ant-design-pro' +import { Ellipsis } from 'components' import styles from './List.less' @withI18n() diff --git a/src/pages/request/index.js b/src/pages/request/index.js index 6024b20..22a30e5 100644 --- a/src/pages/request/index.js +++ b/src/pages/request/index.js @@ -1,10 +1,8 @@ import React from 'react' import { request } from 'utils' import { apiPrefix } from 'utils/config' -import { Row, Col, Select, Input, Button, List, Tag, Checkbox } from 'antd' +import { Row, Col, Select, Form, Input, Button, List, Tag, Checkbox } from 'antd' import classnames from 'classnames' -import { Form } from '@ant-design/compatible' -import '@ant-design/compatible/assets/index.css' import { CloseOutlined } from '@ant-design/icons' import { Trans } from '@lingui/react' import api from '@/services/api' @@ -38,7 +36,6 @@ const requests = Object.values(api).map(item => { }) let uuid = 2 -@Form.create() class RequestPage extends React.Component { constructor(props) { super(props) @@ -188,7 +185,7 @@ class RequestPage extends React.Component { Send - +
- {getFieldDecorator(`check[${key}]`, { - initialValue: true, - })()} + + + - {getFieldDecorator(`key[${key}]`)( + - )} + - {getFieldDecorator(`value[${key}]`)( + - )} +
- +
{result}
diff --git a/src/pages/user/components/Filter.js b/src/pages/user/components/Filter.js index 021863a..c4a64fa 100644 --- a/src/pages/user/components/Filter.js +++ b/src/pages/user/components/Filter.js @@ -3,12 +3,8 @@ import PropTypes from 'prop-types' import moment from 'moment' import { FilterItem } from 'components' -/* global document */ -import { Form } from '@ant-design/compatible' - -import '@ant-design/compatible/assets/index.css' import { Trans, withI18n } from '@lingui/react' -import { Button, Row, Col, DatePicker, Input, Cascader } from 'antd' +import { Button, Row, Col, DatePicker, Form, Input, Cascader } from 'antd' import city from 'utils/city' const { Search } = Input @@ -28,7 +24,6 @@ const TwoColProps = { } @withI18n() -@Form.create() class Filter extends Component { handleFields = fields => { const { createTime } = fields @@ -42,7 +37,8 @@ class Filter extends Component { } handleSubmit = () => { - const { onFilterChange, form } = this.props + const { onFilterChange } = this.props + const [form] = Form.useForm() const { getFieldsValue } = form let fields = getFieldsValue() @@ -51,7 +47,7 @@ class Filter extends Component { } handleReset = () => { - const { form } = this.props + const [form] = Form.useForm() const { getFieldsValue, setFieldsValue } = form const fields = getFieldsValue() @@ -78,7 +74,8 @@ class Filter extends Component { } render() { - const { onAdd, filter, form, i18n } = this.props + const { onAdd, filter, i18n } = this.props + const [form] = Form.useForm() const { getFieldDecorator } = form const { name, address } = filter @@ -91,14 +88,15 @@ class Filter extends Component { } return ( +
- {getFieldDecorator('name', { initialValue: name })( + - )} + placeholder={i18n.t`Search Name`} + onSearch={this.handleSubmit} + /> + - {getFieldDecorator('address', { initialValue: address })( + - )} + - {getFieldDecorator('createTime', { - initialValue: initialCreateTime, - })( + - )} + - +
) } } diff --git a/src/pages/user/components/Modal.js b/src/pages/user/components/Modal.js index 4c2348c..7827d5d 100644 --- a/src/pages/user/components/Modal.js +++ b/src/pages/user/components/Modal.js @@ -1,8 +1,6 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' -import { Input, InputNumber, Radio, Modal, Cascader } from 'antd' -import { Form } from '@ant-design/compatible' -import '@ant-design/compatible/assets/index.css' +import { Form, Input, InputNumber, Radio, Modal, Cascader } from 'antd' import { Trans, withI18n } from '@lingui/react' import city from 'utils/city' @@ -17,10 +15,10 @@ const formItemLayout = { }, } @withI18n() -@Form.create() class UserModal extends PureComponent { handleOk = () => { - const { item = {}, onOk, form } = this.props + const { item = {}, onOk } = this.props + const [form] = Form.useForm() const { validateFields, getFieldsValue } = form validateFields(errors => { @@ -42,37 +40,17 @@ class UserModal extends PureComponent { return ( -
- - {getFieldDecorator('name', { - initialValue: item.name, - rules: [ - { - required: true, - }, - ], - })()} + + + - - {getFieldDecorator('nickName', { - initialValue: item.nickName, - rules: [ - { - required: true, - }, - ], - })()} + + - - {getFieldDecorator('isMale', { - initialValue: item.isMale, - rules: [ - { - required: true, - type: 'boolean', - }, - ], - })( + Male @@ -81,58 +59,25 @@ class UserModal extends PureComponent { Female - )} - - {getFieldDecorator('age', { - initialValue: item.age, - rules: [ - { - required: true, - type: 'number', - }, - ], - })()} + + - - {getFieldDecorator('phone', { - initialValue: item.phone, - rules: [ - { - required: true, - pattern: /^1[34578]\d{9}$/, - message: i18n.t`The input is not valid phone!`, - }, - ], - })()} + + - - {getFieldDecorator('email', { - initialValue: item.email, - rules: [ - { - required: true, - pattern: /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/, - message: i18n.t`The input is not valid E-mail!`, - }, - ], - })()} + + - - {getFieldDecorator('address', { - initialValue: item.address && item.address.split(' '), - rules: [ - { - required: true, - }, - ], - })( + - )}