deleteUser
This commit is contained in:
		
							parent
							
								
									40e0e2dd77
								
							
						
					
					
						commit
						31fc03a654
					
				| @ -4,6 +4,7 @@ import { | |||||||
|   LoginInputDto, |   LoginInputDto, | ||||||
|   RegisterInputDto, |   RegisterInputDto, | ||||||
|   ForgetPasswordInputDto, |   ForgetPasswordInputDto, | ||||||
|  |   DeleteUser, | ||||||
|   Token, |   Token, | ||||||
|   TokenRefreshPayload, |   TokenRefreshPayload, | ||||||
|   User, |   User, | ||||||
| @ -21,6 +22,10 @@ export async function forgetPassword(data: ForgetPasswordInputDto) { | |||||||
|   return axios.patch<Token>('/api/users/password', data) |   return axios.patch<Token>('/api/users/password', data) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export async function deleteUser(data: DeleteUser) { | ||||||
|  |   return axios.delete('/api/users/me', { data }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| let refreshing: Promise<AxiosResponse<Token>> | null | let refreshing: Promise<AxiosResponse<Token>> | null | ||||||
| export async function refreshToken(data: TokenRefreshPayload) { | export async function refreshToken(data: TokenRefreshPayload) { | ||||||
|   if (!refreshing) { |   if (!refreshing) { | ||||||
|  | |||||||
| @ -18,6 +18,11 @@ export interface ForgetPasswordInputDto extends EmailVerifyDto { | |||||||
|   password: string |   password: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** 删除账户入参 */ | ||||||
|  | export interface DeleteUser extends EmailVerifyDto { | ||||||
|  |   password: string | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export interface Token { | export interface Token { | ||||||
|   accessToken: string |   accessToken: string | ||||||
|   refreshToken: string |   refreshToken: string | ||||||
|  | |||||||
							
								
								
									
										146
									
								
								src/pages/components/DeleteUser.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								src/pages/components/DeleteUser.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,146 @@ | |||||||
|  | import * as React from 'react' | ||||||
|  | import { useUser } from '@/utils/useUser' | ||||||
|  | import { useFormik } from 'formik' | ||||||
|  | import { useRouter } from 'next/router' | ||||||
|  | import Button from '@mui/material/Button' | ||||||
|  | import TextField from '@mui/material/TextField' | ||||||
|  | import Dialog from '@mui/material/Dialog' | ||||||
|  | import DialogActions from '@mui/material/DialogActions' | ||||||
|  | import DialogContent from '@mui/material/DialogContent' | ||||||
|  | import DialogContentText from '@mui/material/DialogContentText' | ||||||
|  | import DialogTitle from '@mui/material/DialogTitle' | ||||||
|  | import Grid from '@mui/material/Unstable_Grid2' | ||||||
|  | import { DeleteUser } from '@/api/user.interface' | ||||||
|  | import { EmailVerifyCodeScene } from '@/api/email.interface' | ||||||
|  | import * as yup from '@/utils/validation' | ||||||
|  | import * as api from '@/api' | ||||||
|  | import { useCountdown, COUNTDOWN_SECONDS } from '@/utils/useCountdown' | ||||||
|  | import { toast } from 'react-toastify' | ||||||
|  | 
 | ||||||
|  | export function DeleteUser() { | ||||||
|  |   const { user } = useUser() | ||||||
|  |   const router = useRouter() | ||||||
|  |   const [open, setOpen] = React.useState(false) | ||||||
|  |   const [confirm, setConfrim] = React.useState(false) | ||||||
|  |   const { countdown, setCountdown } = useCountdown() | ||||||
|  | 
 | ||||||
|  |   const formik = useFormik<DeleteUser>({ | ||||||
|  |     initialValues: { | ||||||
|  |       email: user!.email, | ||||||
|  |       password: '', | ||||||
|  |       verifyCode: '', | ||||||
|  |       token: '', | ||||||
|  |     }, | ||||||
|  |     validateOnChange: false, | ||||||
|  |     validationSchema: yup.object({ | ||||||
|  |       verifyCode: yup.verifyCodeSchema, | ||||||
|  |     }), | ||||||
|  |     onSubmit: async (values) => { | ||||||
|  |       await api.user.deleteUser(values) | ||||||
|  |       localStorage.removeItem('accessToken') | ||||||
|  |       localStorage.removeItem('refreshToken') | ||||||
|  |       toast.success('用户删除成功') | ||||||
|  |       router.push('/login') | ||||||
|  |     }, | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   async function sendVerifyCode() { | ||||||
|  |     setCountdown(COUNTDOWN_SECONDS) | ||||||
|  |     try { | ||||||
|  |       const res = await api.email.sendEmailVerifyCode({ | ||||||
|  |         email: formik.values.email, | ||||||
|  |         scene: EmailVerifyCodeScene.deleteUser, | ||||||
|  |       }) | ||||||
|  |       formik.setFieldValue('token', res.data.token) | ||||||
|  |     } catch (err) { | ||||||
|  |       setCountdown(0) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <> | ||||||
|  |       <Button color="error" onClick={() => setOpen(true)}> | ||||||
|  |         删除用户 | ||||||
|  |       </Button> | ||||||
|  |       <Dialog | ||||||
|  |         open={open} | ||||||
|  |         fullWidth | ||||||
|  |         maxWidth="xs" | ||||||
|  |         onClose={() => setOpen(false)} | ||||||
|  |       > | ||||||
|  |         <DialogTitle>删除用户</DialogTitle> | ||||||
|  |         <DialogContent dividers> | ||||||
|  |           <TextField | ||||||
|  |             {...formik.getFieldProps('email')} | ||||||
|  |             disabled | ||||||
|  |             helperText={' '} | ||||||
|  |             fullWidth | ||||||
|  |             label="邮箱" | ||||||
|  |             sx={{ mt: 1 }} | ||||||
|  |           /> | ||||||
|  |           <Grid container spacing={2}> | ||||||
|  |             <Grid> | ||||||
|  |               <TextField | ||||||
|  |                 {...formik.getFieldProps('verifyCode')} | ||||||
|  |                 required | ||||||
|  |                 error={formik.touched.verifyCode && !!formik.errors.verifyCode} | ||||||
|  |                 helperText={ | ||||||
|  |                   (formik.touched.verifyCode && formik.errors.verifyCode) || ' ' | ||||||
|  |                 } | ||||||
|  |                 fullWidth | ||||||
|  |                 label="验证码" | ||||||
|  |                 autoComplete="verifyCode" | ||||||
|  |                 autoFocus | ||||||
|  |                 sx={{ mt: 1 }} | ||||||
|  |               /> | ||||||
|  |             </Grid> | ||||||
|  |             <Grid mt={2} sx={{ flexGrow: 1 }}> | ||||||
|  |               <Button | ||||||
|  |                 size="large" | ||||||
|  |                 fullWidth | ||||||
|  |                 variant="contained" | ||||||
|  |                 disabled={countdown > 0} | ||||||
|  |                 onClick={sendVerifyCode} | ||||||
|  |               > | ||||||
|  |                 {countdown > 0 ? countdown : '发送验证码'} | ||||||
|  |               </Button> | ||||||
|  |             </Grid> | ||||||
|  |           </Grid> | ||||||
|  |           <TextField | ||||||
|  |             {...formik.getFieldProps('password')} | ||||||
|  |             required | ||||||
|  |             error={formik.touched.password && !!formik.errors.password} | ||||||
|  |             helperText={ | ||||||
|  |               (formik.touched.password && formik.errors.password) || ' ' | ||||||
|  |             } | ||||||
|  |             fullWidth | ||||||
|  |             label="密码" | ||||||
|  |             type="password" | ||||||
|  |             autoComplete="current-password" | ||||||
|  |             sx={{ mt: 1 }} | ||||||
|  |           /> | ||||||
|  |         </DialogContent> | ||||||
|  |         <DialogActions> | ||||||
|  |           <Button onClick={() => setOpen(false)}>取消</Button> | ||||||
|  |           <Button color="error" onClick={() => setConfrim(true)}> | ||||||
|  |             删除 | ||||||
|  |           </Button> | ||||||
|  |         </DialogActions> | ||||||
|  |       </Dialog> | ||||||
|  |       <Dialog maxWidth="xs" open={confirm}> | ||||||
|  |         <DialogTitle>确定删除?</DialogTitle> | ||||||
|  |         <DialogContent dividers> | ||||||
|  |           <DialogContentText> | ||||||
|  |             该用户的所有数据将被不可逆地抹除! | ||||||
|  |           </DialogContentText> | ||||||
|  |         </DialogContent> | ||||||
|  |         <DialogActions> | ||||||
|  |           <Button onClick={() => setConfrim(false)}>取消</Button> | ||||||
|  |           <Button color="error" type="submit" onClick={formik.submitForm}> | ||||||
|  |             确定删除 | ||||||
|  |           </Button> | ||||||
|  |         </DialogActions> | ||||||
|  |       </Dialog> | ||||||
|  |     </> | ||||||
|  |   ) | ||||||
|  | } | ||||||
| @ -3,6 +3,7 @@ import { useUser } from '@/utils/useUser' | |||||||
| import Alert from '@mui/material/Alert' | import Alert from '@mui/material/Alert' | ||||||
| import Button from '@mui/material/Button' | import Button from '@mui/material/Button' | ||||||
| import { useRouter } from 'next/router' | import { useRouter } from 'next/router' | ||||||
|  | import { DeleteUser } from './components/DeleteUser' | ||||||
| 
 | 
 | ||||||
| export default function Home() { | export default function Home() { | ||||||
|   const { user, isLoading, errMsg } = useUser() |   const { user, isLoading, errMsg } = useUser() | ||||||
| @ -34,7 +35,8 @@ export default function Home() { | |||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       <Alert severity="success">hello {user!.email}</Alert> |       <Alert severity="success">hello {user!.email}</Alert> | ||||||
|       <Button onClick={logout}>注销</Button> |       <Button onClick={logout}>退出登录</Button> | ||||||
|  |       <DeleteUser /> | ||||||
|     </> |     </> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,13 +1,13 @@ | |||||||
| import useSWR from 'swr' | import useSWR from 'swr' | ||||||
| import * as api from '@/api' | import * as api from '@/api' | ||||||
| import type { AxiosError, AxiosResponse } from 'axios' | import type { AxiosError, AxiosResponse } from 'axios' | ||||||
| import { UserEntity } from '@/api/user' | import { User } from '@/api/user.interface' | ||||||
| 
 | 
 | ||||||
| export function useUser() { | export function useUser() { | ||||||
|   const { data, error, isLoading } = useSWR< |   const { data, error, isLoading } = useSWR<AxiosResponse<User>, AxiosError>( | ||||||
|     AxiosResponse<UserEntity>, |     `user`, | ||||||
|     AxiosError |     api.user.getUserInfo, | ||||||
|   >(`user`, api.user.getUserInfo) |   ) | ||||||
| 
 | 
 | ||||||
|   const user = data?.data ?? null |   const user = data?.data ?? null | ||||||
|   const errMsg = error?.message ?? '' |   const errMsg = error?.message ?? '' | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user