From 704eb3fa3e8fbdad1401f96422c1cad803ab4d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=B8=85?= Date: Mon, 2 Nov 2020 04:04:19 -0600 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20use=20ProForm=20replace=20c?= =?UTF-8?q?ompents=20form=20(#7544)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat: use ProForm replace compents form * up version * fix lint error --- mock/user.ts | 15 +- package.json | 4 +- src/locales/zh-CN.ts | 2 + src/locales/zh-CN/pages.ts | 23 ++ src/models/login.ts | 2 + .../login/components/Login/LoginContext.tsx | 13 - .../user/login/components/Login/LoginItem.tsx | 177 ---------- .../login/components/Login/LoginSubmit.tsx | 23 -- .../user/login/components/Login/LoginTab.tsx | 45 --- .../user/login/components/Login/index.less | 49 --- .../user/login/components/Login/index.tsx | 119 ------- src/pages/user/login/components/Login/map.tsx | 72 ---- .../user/login/{style.less => index.less} | 19 +- src/pages/user/login/index.tsx | 334 ++++++++++-------- tsconfig.json | 1 + 15 files changed, 250 insertions(+), 648 deletions(-) create mode 100644 src/locales/zh-CN/pages.ts delete mode 100644 src/pages/user/login/components/Login/LoginContext.tsx delete mode 100644 src/pages/user/login/components/Login/LoginItem.tsx delete mode 100644 src/pages/user/login/components/Login/LoginSubmit.tsx delete mode 100644 src/pages/user/login/components/Login/LoginTab.tsx delete mode 100644 src/pages/user/login/components/Login/index.less delete mode 100644 src/pages/user/login/components/Login/index.tsx delete mode 100644 src/pages/user/login/components/Login/map.tsx rename src/pages/user/login/{style.less => index.less} (72%) diff --git a/mock/user.ts b/mock/user.ts index 0a7f305b..a722c228 100644 --- a/mock/user.ts +++ b/mock/user.ts @@ -1,8 +1,18 @@ import { Request, Response } from 'express'; -function getFakeCaptcha(req: Request, res: Response) { +const waitTime = (time: number = 100) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(true); + }, time); + }); +}; + +async function getFakeCaptcha(req: Request, res: Response) { + await waitTime(2000); return res.json('captcha-xxx'); } + // 代码中会兼容本地 service mock 以及部署站点的静态数据 export default { // 支持值为 Object 和 Array @@ -77,8 +87,9 @@ export default { address: 'Sidney No. 1 Lake Park', }, ], - 'POST /api/login/account': (req: Request, res: Response) => { + 'POST /api/login/account': async (req: Request, res: Response) => { const { password, userName, type } = req.body; + await waitTime(2000); if (password === 'ant.design' && userName === 'admin') { res.send({ status: 'ok', diff --git a/package.json b/package.json index aa3843ac..fdb93151 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ant-design-pro", - "version": "4.2.2", + "version": "4.3.0", "private": true, "description": "An out-of-box UI solution for enterprise applications", "scripts": { @@ -55,7 +55,7 @@ "dependencies": { "@ant-design/icons": "^4.0.0", "@ant-design/pro-descriptions": "^1.0.19", - "@ant-design/pro-form": "^1.0.2", + "@ant-design/pro-form": "^1.2.0", "@ant-design/pro-layout": "^6.4.19", "@ant-design/pro-table": "^2.9.5", "@umijs/route-utils": "^1.0.33", diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 1822d7ba..565b2c33 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -4,6 +4,7 @@ import menu from './zh-CN/menu'; import pwa from './zh-CN/pwa'; import settingDrawer from './zh-CN/settingDrawer'; import settings from './zh-CN/settings'; +import pages from './zh-CN/pages'; export default { 'navBar.lang': '语言', @@ -13,6 +14,7 @@ export default { 'app.preview.down.block': '下载此页面到本地项目', 'app.welcome.link.fetch-blocks': '获取全部区块', 'app.welcome.link.block-list': '基于 block 开发,快速构建标准页面', + ...pages, ...globalHeader, ...menu, ...settingDrawer, diff --git a/src/locales/zh-CN/pages.ts b/src/locales/zh-CN/pages.ts new file mode 100644 index 00000000..e160d9c4 --- /dev/null +++ b/src/locales/zh-CN/pages.ts @@ -0,0 +1,23 @@ +export default { + 'pages.layouts.userLayout.title': 'Ant Design 是西湖区最具影响力的 Web 设计规范', + 'pages.login.accountLogin.tab': '账户密码登录', + 'pages.login.accountLogin.errorMessage': '错误的用户名和密码(admin/ant.design)', + 'pages.login.username.placeholder': '用户名: admin or user', + 'pages.login.username.required': '用户名是必填项!', + 'pages.login.password.placeholder': '密码: ant.design', + 'pages.login.password.required': '密码是必填项!', + 'pages.login.phoneLogin.tab': '手机号登录', + 'pages.login.phoneLogin.errorMessage': '验证码错误', + 'pages.login.phoneNumber.placeholder': '请输入手机号!', + 'pages.login.phoneNumber.required': '手机号是必填项!', + 'pages.login.phoneNumber.invalid': '不合法的手机号!', + 'pages.login.captcha.placeholder': '请输入验证码!', + 'pages.login.captcha.required': '验证码是必填项!', + 'pages.login.phoneLogin.getVerificationCode': '获取验证码', + 'pages.getCaptchaSecondText': '秒后重新获取', + 'pages.login.rememberMe': '自动登录', + 'pages.login.forgotPassword': '忘记密码 ?', + 'pages.login.submit': '提交', + 'pages.login.loginWith': '其他登录方式 :', + 'pages.login.registerAccount': '注册账户', +}; diff --git a/src/models/login.ts b/src/models/login.ts index 2a323c18..173fc072 100644 --- a/src/models/login.ts +++ b/src/models/login.ts @@ -4,6 +4,7 @@ import { history, Reducer, Effect } from 'umi'; import { fakeAccountLogin } from '@/services/login'; import { setAuthority } from '@/utils/authority'; import { getPageQuery } from '@/utils/utils'; +import { message } from 'antd'; export interface StateType { status?: 'ok' | 'error'; @@ -41,6 +42,7 @@ const Model: LoginModelType = { if (response.status === 'ok') { const urlParams = new URL(window.location.href); const params = getPageQuery(); + message.success('🎉 🎉 🎉 登录成功!'); let { redirect } = params as { redirect: string }; if (redirect) { const redirectUrlParams = new URL(redirect); diff --git a/src/pages/user/login/components/Login/LoginContext.tsx b/src/pages/user/login/components/Login/LoginContext.tsx deleted file mode 100644 index ae571e0d..00000000 --- a/src/pages/user/login/components/Login/LoginContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { createContext } from 'react'; - -export interface LoginContextProps { - 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/src/pages/user/login/components/Login/LoginItem.tsx b/src/pages/user/login/components/Login/LoginItem.tsx deleted file mode 100644 index 9df1b630..00000000 --- a/src/pages/user/login/components/Login/LoginItem.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import { Button, Col, Input, Row, Form, message } from 'antd'; -import React, { useState, useCallback, useEffect } from 'react'; -import omit from 'omit.js'; -import { FormItemProps } from 'antd/es/form/FormItem'; -import { getFakeCaptcha } from '@/services/login'; -import { FormattedMessage } from 'umi'; - -import ItemMap from './map'; -import LoginContext, { LoginContextProps } from './LoginContext'; -import styles from './index.less'; - -export type WrappedLoginItemProps = LoginItemProps; -export type LoginItemKeyType = keyof typeof ItemMap; -export interface LoginItemType { - UserName: React.FC; - Password: React.FC; - Mobile: React.FC; - Captcha: React.FC; -} - -export interface LoginItemProps extends Partial { - name?: string; - style?: React.CSSProperties; - placeholder?: string; - buttonText?: React.ReactNode; - countDown?: number; - getCaptchaButtonText?: string; - getCaptchaSecondText?: string; - updateActive?: LoginContextProps['updateActive']; - type?: string; - defaultValue?: string; - customProps?: { [key: string]: unknown }; - onChange?: (e: React.ChangeEvent) => void; - tabUtil?: LoginContextProps['tabUtil']; -} - -const FormItem = Form.Item; - -const getFormItemOptions = ({ - onChange, - defaultValue, - customProps = {}, - rules, -}: LoginItemProps) => { - const options: { - rules?: LoginItemProps['rules']; - onChange?: LoginItemProps['onChange']; - initialValue?: LoginItemProps['defaultValue']; - } = { - rules: rules || (customProps.rules as LoginItemProps['rules']), - }; - if (onChange) { - options.onChange = onChange; - } - if (defaultValue) { - options.initialValue = defaultValue; - } - return options; -}; - -const LoginItem: React.FC = (props) => { - const [count, setCount] = useState(props.countDown || 0); - const [timing, setTiming] = useState(false); - // 这么写是为了防止restProps中 带入 onChange, defaultValue, rules props tabUtil - const { - onChange, - customProps, - defaultValue, - rules, - name, - getCaptchaButtonText, - getCaptchaSecondText, - updateActive, - type, - tabUtil, - ...restProps - } = props; - - const onGetCaptcha = useCallback(async (mobile: string) => { - const result = await getFakeCaptcha(mobile); - if (result === false) { - return; - } - message.success('获取验证码成功!验证码为:1234'); - setTiming(true); - }, []); - - useEffect(() => { - let interval: number = 0; - const { countDown } = props; - if (timing) { - interval = window.setInterval(() => { - setCount((preSecond) => { - if (preSecond <= 1) { - setTiming(false); - clearInterval(interval); - // 重置秒数 - return countDown || 60; - } - return preSecond - 1; - }); - }, 1000); - } - return () => clearInterval(interval); - }, [timing]); - if (!name) { - return null; - } - // get getFieldDecorator props - const options = getFormItemOptions(props); - const otherProps = restProps || {}; - - if (type === 'Captcha') { - const inputProps = omit(otherProps, ['onGetCaptcha', 'countDown']); - - return ( - - {({ getFieldValue }) => ( - - - - - - - - - - - )} - - ); - } - return ( - - - - ); -}; - -const LoginItems: Partial = {}; - -Object.keys(ItemMap).forEach((key) => { - const item = ItemMap[key]; - LoginItems[key] = (props: LoginItemProps) => ( - - {(context) => ( - - )} - - ); -}); - -export default LoginItems as LoginItemType; diff --git a/src/pages/user/login/components/Login/LoginSubmit.tsx b/src/pages/user/login/components/Login/LoginSubmit.tsx deleted file mode 100644 index 280fb0fc..00000000 --- a/src/pages/user/login/components/Login/LoginSubmit.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { Button, Form } from 'antd'; - -import { ButtonProps } from 'antd/es/button'; -import React from 'react'; -import classNames from 'classnames'; -import styles from './index.less'; - -const FormItem = Form.Item; - -interface LoginSubmitProps extends ButtonProps { - className?: string; -} - -const LoginSubmit: React.FC = ({ className, ...rest }) => { - const clsString = classNames(styles.submit, className); - return ( - -