From f0d97f9b21da120d712a2b34c7d884bfe6d152fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=B8=85?= Date: Thu, 18 Apr 2019 19:21:02 +0800 Subject: [PATCH] add LoginContext --- .umirc.js | 2 +- UserLogin/src/{_mock.js => _mock.ts} | 0 .../src/components/Login/LoginContext.tsx | 13 ++ UserLogin/src/components/Login/LoginItem.tsx | 189 ++++++++++++++++++ .../src/components/Login/LoginSubmit.tsx | 21 ++ UserLogin/src/components/Login/LoginTab.tsx | 46 +++++ UserLogin/src/components/Login/index.less | 53 +++++ UserLogin/src/components/Login/index.tsx | 152 ++++++++++++++ UserLogin/src/components/Login/map.tsx | 65 ++++++ UserLogin/src/{index.js => index.tsx} | 11 +- UserLogin/src/locales/{en-US.js => en-US.ts} | 0 UserLogin/src/locales/{zh-CN.js => zh-CN.ts} | 0 UserLogin/src/locales/{zh-TW.js => zh-TW.ts} | 0 UserLogin/src/{model.js => model.ts} | 3 - UserLogin/src/{service.js => service.ts} | 0 UserLogin/src/utils/Authorized.js | 12 -- UserLogin/src/utils/authority.js | 22 -- package.json | 2 +- 18 files changed, 546 insertions(+), 45 deletions(-) rename UserLogin/src/{_mock.js => _mock.ts} (100%) create mode 100644 UserLogin/src/components/Login/LoginContext.tsx create mode 100644 UserLogin/src/components/Login/LoginItem.tsx create mode 100644 UserLogin/src/components/Login/LoginSubmit.tsx create mode 100644 UserLogin/src/components/Login/LoginTab.tsx create mode 100644 UserLogin/src/components/Login/index.less create mode 100644 UserLogin/src/components/Login/index.tsx create mode 100644 UserLogin/src/components/Login/map.tsx rename UserLogin/src/{index.js => index.tsx} (97%) rename UserLogin/src/locales/{en-US.js => en-US.ts} (100%) rename UserLogin/src/locales/{zh-CN.js => zh-CN.ts} (100%) rename UserLogin/src/locales/{zh-TW.js => zh-TW.ts} (100%) rename UserLogin/src/{model.js => model.ts} (91%) rename UserLogin/src/{service.js => service.ts} (100%) delete mode 100644 UserLogin/src/utils/Authorized.js delete mode 100644 UserLogin/src/utils/authority.js diff --git a/.umirc.js b/.umirc.js index 85f1038f..75ec0fc9 100644 --- a/.umirc.js +++ b/.umirc.js @@ -3,7 +3,7 @@ export default { [ 'umi-plugin-block-dev', { - layout: 'ant-design-pro', + layout: 'ant-design-pro-user', menu: { name: '主页', icon: 'home', diff --git a/UserLogin/src/_mock.js b/UserLogin/src/_mock.ts similarity index 100% rename from UserLogin/src/_mock.js rename to UserLogin/src/_mock.ts diff --git a/UserLogin/src/components/Login/LoginContext.tsx b/UserLogin/src/components/Login/LoginContext.tsx new file mode 100644 index 00000000..6e46556f --- /dev/null +++ b/UserLogin/src/components/Login/LoginContext.tsx @@ -0,0 +1,13 @@ +import { createContext } from 'react'; + +export interface ILoginContext { + tabUtil?: { + addTab: (id: string) => void; + removeTab: (id: string) => void; + }; + updateActive?: (activeItem: { [key: string]: string } | string) => void; +} + +const LoginContext: React.Context = createContext({}); + +export default LoginContext; diff --git a/UserLogin/src/components/Login/LoginItem.tsx b/UserLogin/src/components/Login/LoginItem.tsx new file mode 100644 index 00000000..e3694eff --- /dev/null +++ b/UserLogin/src/components/Login/LoginItem.tsx @@ -0,0 +1,189 @@ +import React, { Component } from 'react'; +import { Form, Input, Button, Row, Col } from 'antd'; +import omit from 'omit.js'; +import styles from './index.less'; +import ItemMap from './map'; +import LoginContext, { ILoginContext } from './loginContext'; +import { FormComponentProps } from 'antd/lib/form'; + +type Omit = Pick>; + +export type WrappedLoginItemProps = Omit; +export type LoginItemKeyType = keyof typeof ItemMap; +export type LoginItemType = { [K in keyof typeof ItemMap]: React.FC }; + +export interface LoginItemProps extends FormComponentProps { + name?: string; + rules?: any[]; + style?: React.CSSProperties; + onGetCaptcha?: (event?: MouseEvent) => void | Promise | false; + placeholder?: string; + buttonText?: React.ReactNode; + onPressEnter?: (e: any) => void; + countDown?: number; + getCaptchaButtonText?: string; + getCaptchaSecondText?: string; + updateActive: ILoginContext['updateActive']; + type: string; + defaultValue?: string; + customProps?: { [key: string]: any }; + onChange?: (e: any) => void; +} + +interface LoginItemState { + count: number; +} + +const FormItem = Form.Item; + +class WrapFormItem extends Component { + static defaultProps = { + getCaptchaButtonText: 'captcha', + getCaptchaSecondText: 'second', + }; + + constructor(props: LoginItemProps) { + super(props); + this.state = { + count: 0, + }; + } + interval: number | undefined; + componentDidMount() { + const { updateActive, name = '' } = this.props; + if (updateActive) { + updateActive(name); + } + } + + componentWillUnmount() { + clearInterval(this.interval); + } + + onGetCaptcha = () => { + const { onGetCaptcha } = this.props; + const result = onGetCaptcha ? onGetCaptcha() : null; + if (result === false) { + return; + } + if (result instanceof Promise) { + result.then(this.runGetCaptchaCountDown); + } else { + this.runGetCaptchaCountDown(); + } + }; + + getFormItemOptions = ({ onChange, defaultValue, customProps = {}, rules }: LoginItemProps) => { + const options: { + rules?: Array; + onChange?: LoginItemProps['onChange']; + initialValue?: LoginItemProps['defaultValue']; + } = { + rules: rules || customProps.rules, + }; + if (onChange) { + options.onChange = onChange; + } + if (defaultValue) { + options.initialValue = defaultValue; + } + return options; + }; + + runGetCaptchaCountDown = () => { + const { countDown } = this.props; + let count = countDown || 59; + this.setState({ count }); + this.interval = window.setInterval(() => { + count -= 1; + this.setState({ count }); + if (count === 0) { + clearInterval(this.interval); + } + }, 1000); + }; + + render() { + const { count } = this.state; + + // 这么写是为了防止restProps中 带入 onChange, defaultValue, rules props + const { + onChange, + customProps, + defaultValue, + rules, + name, + getCaptchaButtonText, + getCaptchaSecondText, + updateActive, + type, + form, + ...restProps + } = this.props; + if (!name) { + console.warn('name is required!'); + return null; + } + console.log(form); + if (!form) { + return null; + } + const { getFieldDecorator } = form; + // get getFieldDecorator props + const options = this.getFormItemOptions(this.props); + + const otherProps = restProps || {}; + if (type === 'Captcha') { + const inputProps = omit(otherProps, ['onGetCaptcha', 'countDown']); + return ( + + + + {getFieldDecorator(name, options)()} + + + + + + + ); + } + return ( + + {getFieldDecorator(name, options)()} + + ); + } +} + +const LoginItem: Partial = {}; + +Object.keys(ItemMap).forEach(key => { + const item = ItemMap[key]; + LoginItem[key] = (props: LoginItemProps) => ( + + {context => { + console.log(context); + return ( + + ); + }} + + ); +}); + +export default LoginItem as LoginItemType; diff --git a/UserLogin/src/components/Login/LoginSubmit.tsx b/UserLogin/src/components/Login/LoginSubmit.tsx new file mode 100644 index 00000000..2a6c246c --- /dev/null +++ b/UserLogin/src/components/Login/LoginSubmit.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import classNames from 'classnames'; +import { Button, Form } from 'antd'; +import styles from './index.less'; +import { ButtonProps } from 'antd/lib/button'; +const FormItem = Form.Item; + +interface LoginSubmitProps extends ButtonProps { + className: string; +} + +const LoginSubmit: React.SFC = ({ className, ...rest }) => { + const clsString = classNames(styles.submit, className); + return ( + +