From 95400da337572d3330a226ff2e95b99295cbf077 Mon Sep 17 00:00:00 2001 From: fantasticit Date: Sun, 3 Jul 2022 09:51:25 +0800 Subject: [PATCH] feat: improve update user, reset password --- packages/client/src/components/user/index.tsx | 15 +- .../components/user/reset-password/index.tsx | 112 +++++++++++++++ .../src/components/user/setting/index.tsx | 97 ++++++++++--- .../client/src/pages/forgetPassword/index.tsx | 133 ++---------------- packages/server/src/dtos/update-user.dto.ts | 7 +- packages/server/src/services/user.service.ts | 13 +- .../server/src/services/verify.service.ts | 2 +- 7 files changed, 239 insertions(+), 140 deletions(-) create mode 100644 packages/client/src/components/user/reset-password/index.tsx diff --git a/packages/client/src/components/user/index.tsx b/packages/client/src/components/user/index.tsx index 2d4111e0..ec2d7d08 100644 --- a/packages/client/src/components/user/index.tsx +++ b/packages/client/src/components/user/index.tsx @@ -1,10 +1,11 @@ import { IconSpin } from '@douyinfe/semi-icons'; -import { Avatar, Button, Dropdown, Typography } from '@douyinfe/semi-ui'; +import { Avatar, Button, Dropdown, Modal, Toast, Typography } from '@douyinfe/semi-ui'; import { useUser } from 'data/user'; import { useToggle } from 'hooks/use-toggle'; import Router from 'next/router'; import React, { useCallback } from 'react'; +import { ResetPassword } from './reset-password'; import { UserSetting } from './setting'; const { Text } = Typography; @@ -12,11 +13,17 @@ const { Text } = Typography; export const User: React.FC = () => { const { user, loading, error, toLogin, logout } = useUser(); const [visible, toggleVisible] = useToggle(false); + const [resetVisible, toggleResetVisible] = useToggle(false); const toAdmin = useCallback(() => { Router.push('/admin'); }, []); + const onResetSuccess = useCallback(() => { + Toast.success('请重新登录'); + Router.replace(`/login?redirect=${Router.asPath}`); + }, []); + if (loading) return + + + + + + + + + + ); +}; diff --git a/packages/client/src/components/user/setting/index.tsx b/packages/client/src/components/user/setting/index.tsx index 9360655a..82ebdd74 100644 --- a/packages/client/src/components/user/setting/index.tsx +++ b/packages/client/src/components/user/setting/index.tsx @@ -1,8 +1,10 @@ -import { Avatar, Form, Modal, Space } from '@douyinfe/semi-ui'; +import { Avatar, Button, Col, Form, Modal, Row, Space, Toast } from '@douyinfe/semi-ui'; import { FormApi } from '@douyinfe/semi-ui/lib/es/form'; import { Upload } from 'components/upload'; -import { useUser } from 'data/user'; -import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react'; +import { useUser, useVerifyCode } from 'data/user'; +import { useInterval } from 'hooks/use-interval'; +import { useToggle } from 'hooks/use-toggle'; +import { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react'; interface IProps { visible: boolean; @@ -13,24 +15,60 @@ export const UserSetting: React.FC = ({ visible, toggleVisible }) => { const $form = useRef(); const { user, loading, updateUser } = useUser(); const [currentAvatar, setCurrentAvatar] = useState(''); + const [email, setEmail] = useState(''); + const { sendVerifyCode, loading: sendVerifyCodeLoading } = useVerifyCode(); + const [hasSendVerifyCode, toggleHasSendVerifyCode] = useToggle(false); + const [countDown, setCountDown] = useState(0); - const setAvatar = (url) => { + const setAvatar = useCallback((url) => { $form.current.setValue('avatar', url); setCurrentAvatar(url); - }; + }, []); - const handleOk = () => { + const handleOk = useCallback(() => { $form.current.validate().then((values) => { if (!values.email) { delete values.email; } - updateUser(values); - toggleVisible(false); + updateUser(values).then(() => { + Toast.success('账户信息已更新'); + toggleVisible(false); + }); }); - }; - const handleCancel = () => { + }, [toggleVisible, updateUser]); + + const handleCancel = useCallback(() => { toggleVisible(false); - }; + }, [toggleVisible]); + + const onFormChange = useCallback((formState) => { + setEmail(formState.values.email); + }, []); + + const { start, stop } = useInterval(() => { + setCountDown((v) => { + if (v - 1 <= 0) { + stop(); + toggleHasSendVerifyCode(false); + return 0; + } + return v - 1; + }); + }, 1000); + + const getVerifyCode = useCallback(() => { + stop(); + sendVerifyCode({ email }) + .then(() => { + Toast.success('请前往邮箱查收验证码'); + setCountDown(60); + start(); + toggleHasSendVerifyCode(true); + }) + .catch(() => { + toggleHasSendVerifyCode(false); + }); + }, [email, toggleHasSendVerifyCode, sendVerifyCode, start, stop]); useEffect(() => { if (!user || !$form.current) return; @@ -51,6 +89,7 @@ export const UserSetting: React.FC = ({ visible, toggleVisible }) => { initValues={{ avatar: user.avatar, name: user.name, email: user.email }} getFormApi={(formApi) => ($form.current = formApi)} labelPosition="left" + onChange={onFormChange} > @@ -58,6 +97,7 @@ export const UserSetting: React.FC = ({ visible, toggleVisible }) => { + = ({ visible, toggleVisible }) => { disabled placeholder="请输入账户名称" > - + + + + {email && email !== user.email ? ( + + + + + + + + + + + ) : null} ); diff --git a/packages/client/src/pages/forgetPassword/index.tsx b/packages/client/src/pages/forgetPassword/index.tsx index f848ecd0..64d91a06 100644 --- a/packages/client/src/pages/forgetPassword/index.tsx +++ b/packages/client/src/pages/forgetPassword/index.tsx @@ -1,11 +1,9 @@ -import { Button, Col, Form, Layout, Modal, Row, Space, Toast, Typography } from '@douyinfe/semi-ui'; +import { Layout, Modal, Space, Typography } from '@douyinfe/semi-ui'; import { Author } from 'components/author'; import { LogoImage, LogoText } from 'components/logo'; import { Seo } from 'components/seo'; -import { useResetPassword, useVerifyCode } from 'data/user'; -import { useInterval } from 'hooks/use-interval'; +import { ResetPassword } from 'components/user/reset-password'; import { useRouterQuery } from 'hooks/use-router-query'; -import { useToggle } from 'hooks/use-toggle'; import Link from 'next/link'; import Router from 'next/router'; import React, { useCallback, useState } from 'react'; @@ -18,57 +16,17 @@ const { Title, Text } = Typography; const Page = () => { const query = useRouterQuery(); - const [email, setEmail] = useState(''); - const [hasSendVerifyCode, toggleHasSendVerifyCode] = useToggle(false); - const [countDown, setCountDown] = useState(0); - const { reset, loading } = useResetPassword(); - const { sendVerifyCode, loading: sendVerifyCodeLoading } = useVerifyCode(); - - const onFormChange = useCallback((formState) => { - setEmail(formState.values.email); - }, []); - - const { start, stop } = useInterval(() => { - setCountDown((v) => { - if (v - 1 <= 0) { - stop(); - toggleHasSendVerifyCode(false); - return 0; - } - return v - 1; + const onResetSucccess = useCallback(() => { + Modal.confirm({ + title: 密码修改成功, + content: 是否跳转至登录?, + okText: '确认', + cancelText: '取消', + onOk() { + Router.push('/login', { query }); + }, }); - }, 1000); - - const onFinish = useCallback( - (values) => { - reset(values).then((res) => { - Modal.confirm({ - title: 密码修改成功, - content: 是否跳转至登录?, - okText: '确认', - cancelText: '取消', - onOk() { - Router.push('/login', { query }); - }, - }); - }); - }, - [reset, query] - ); - - const getVerifyCode = useCallback(() => { - stop(); - sendVerifyCode({ email }) - .then(() => { - Toast.success('请前往邮箱查收验证码'); - setCountDown(60); - start(); - toggleHasSendVerifyCode(true); - }) - .catch(() => { - toggleHasSendVerifyCode(false); - }); - }, [email, toggleHasSendVerifyCode, sendVerifyCode, start, stop]); + }, [query]); return ( @@ -80,72 +38,11 @@ const Page = () => { -
+
重置密码 - - - - - - - - - - - - - - - - - +
{
- +