### What problem does this PR solve? fix: Login with @tanstack/react-query #1306 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)tags/v0.9.0
| import { useCallback } from 'react'; | |||||
| import { useDispatch } from 'umi'; | |||||
| import { Authorization } from '@/constants/authorization'; | |||||
| import userService from '@/services/user-service'; | |||||
| import authorizationUtil from '@/utils/authorizationUtil'; | |||||
| import { useMutation } from '@tanstack/react-query'; | |||||
| import { message } from 'antd'; | |||||
| import { useTranslation } from 'react-i18next'; | |||||
| import { history } from 'umi'; | |||||
| export interface ILoginRequestBody { | export interface ILoginRequestBody { | ||||
| email: string; | email: string; | ||||
| } | } | ||||
| export const useLogin = () => { | export const useLogin = () => { | ||||
| const dispatch = useDispatch(); | |||||
| const login = useCallback( | |||||
| (requestBody: ILoginRequestBody) => { | |||||
| // TODO: Type needs to be improved | |||||
| return dispatch<any>({ | |||||
| type: 'loginModel/login', | |||||
| payload: requestBody, | |||||
| }); | |||||
| const { t } = useTranslation(); | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['login'], | |||||
| mutationFn: async (params: { email: string; password: string }) => { | |||||
| const { data: res = {}, response } = await userService.login(params); | |||||
| if (res.retcode === 0) { | |||||
| const { data } = res; | |||||
| message.success(t('message.logged')); | |||||
| const authorization = response.headers.get(Authorization); | |||||
| const token = data.access_token; | |||||
| const userInfo = { | |||||
| avatar: data.avatar, | |||||
| name: data.nickname, | |||||
| email: data.email, | |||||
| }; | |||||
| authorizationUtil.setItems({ | |||||
| Authorization: authorization, | |||||
| userInfo: JSON.stringify(userInfo), | |||||
| Token: token, | |||||
| }); | |||||
| } | |||||
| return res.retcode; | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return login; | |||||
| return { data, loading, login: mutateAsync }; | |||||
| }; | }; | ||||
| export const useRegister = () => { | export const useRegister = () => { | ||||
| const dispatch = useDispatch(); | |||||
| const register = useCallback( | |||||
| (requestBody: IRegisterRequestBody) => { | |||||
| return dispatch<any>({ | |||||
| type: 'loginModel/register', | |||||
| payload: requestBody, | |||||
| }); | |||||
| const { t } = useTranslation(); | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['register'], | |||||
| mutationFn: async (params: { | |||||
| email: string; | |||||
| password: string; | |||||
| nickname: string; | |||||
| }) => { | |||||
| const { data = {} } = await userService.register(params); | |||||
| if (data.retcode === 0) { | |||||
| message.success(t('message.registered')); | |||||
| } | |||||
| return data.retcode; | |||||
| }, | |||||
| }); | |||||
| return { data, loading, register: mutateAsync }; | |||||
| }; | |||||
| export const useLogout = () => { | |||||
| const { t } = useTranslation(); | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: ['logout'], | |||||
| mutationFn: async () => { | |||||
| const { data = {} } = await userService.logout(); | |||||
| if (data.retcode === 0) { | |||||
| message.success(t('message.logout')); | |||||
| authorizationUtil.removeAll(); | |||||
| history.push('/login'); | |||||
| } | |||||
| return data.retcode; | |||||
| }, | }, | ||||
| [dispatch], | |||||
| ); | |||||
| }); | |||||
| return register; | |||||
| return { data, loading, logout: mutateAsync }; | |||||
| }; | }; |
| import { ITenantInfo } from '@/interfaces/database/knowledge'; | import { ITenantInfo } from '@/interfaces/database/knowledge'; | ||||
| import { ISystemStatus, IUserInfo } from '@/interfaces/database/userSetting'; | import { ISystemStatus, IUserInfo } from '@/interfaces/database/userSetting'; | ||||
| import userService from '@/services/user-service'; | import userService from '@/services/user-service'; | ||||
| import authorizationUtil from '@/utils/authorizationUtil'; | |||||
| import { useCallback, useEffect, useMemo, useState } from 'react'; | import { useCallback, useEffect, useMemo, useState } from 'react'; | ||||
| import { history, useDispatch, useSelector } from 'umi'; | |||||
| import { useDispatch, useSelector } from 'umi'; | |||||
| export const useFetchUserInfo = () => { | export const useFetchUserInfo = () => { | ||||
| const dispatch = useDispatch(); | const dispatch = useDispatch(); | ||||
| return parserList; | return parserList; | ||||
| }; | }; | ||||
| export const useLogout = () => { | |||||
| const dispatch = useDispatch(); // TODO: clear redux state | |||||
| const logout = useCallback(async () => { | |||||
| const retcode = await dispatch<any>({ type: 'loginModel/logout' }); | |||||
| if (retcode === 0) { | |||||
| authorizationUtil.removeAll(); | |||||
| history.push('/login'); | |||||
| } | |||||
| }, [dispatch]); | |||||
| return logout; | |||||
| }; | |||||
| export const useSaveSetting = () => { | export const useSaveSetting = () => { | ||||
| const dispatch = useDispatch(); | const dispatch = useDispatch(); | ||||
| import { useLogin, useRegister } from '@/hooks/login-hooks'; | import { useLogin, useRegister } from '@/hooks/login-hooks'; | ||||
| import { useOneNamespaceEffectsLoading } from '@/hooks/store-hooks'; | |||||
| import { rsaPsw } from '@/utils'; | import { rsaPsw } from '@/utils'; | ||||
| import { Button, Checkbox, Form, Input } from 'antd'; | import { Button, Checkbox, Form, Input } from 'antd'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| const Login = () => { | const Login = () => { | ||||
| const [title, setTitle] = useState('login'); | const [title, setTitle] = useState('login'); | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const login = useLogin(); | |||||
| const register = useRegister(); | |||||
| const { login, loading: signLoading } = useLogin(); | |||||
| const { register, loading: registerLoading } = useRegister(); | |||||
| const { t } = useTranslation('translation', { keyPrefix: 'login' }); | const { t } = useTranslation('translation', { keyPrefix: 'login' }); | ||||
| // TODO: When the server address request is not accessible, the value of dva-loading always remains true. | |||||
| const signLoading = useOneNamespaceEffectsLoading('loginModel', [ | |||||
| 'login', | |||||
| 'register', | |||||
| ]); | |||||
| const loading = signLoading || registerLoading; | |||||
| const changeTitle = () => { | const changeTitle = () => { | ||||
| setTitle((title) => (title === 'login' ? 'register' : 'login')); | setTitle((title) => (title === 'login' ? 'register' : 'login')); | ||||
| block | block | ||||
| size="large" | size="large" | ||||
| onClick={onCheck} | onClick={onCheck} | ||||
| loading={signLoading} | |||||
| loading={loading} | |||||
| > | > | ||||
| {title === 'login' ? t('login') : t('continue')} | {title === 'login' ? t('login') : t('continue')} | ||||
| </Button> | </Button> |
| import { Authorization } from '@/constants/authorization'; | |||||
| import i18n from '@/locales/config'; | |||||
| import userService from '@/services/user-service'; | |||||
| import authorizationUtil from '@/utils/authorizationUtil'; | |||||
| import { message } from 'antd'; | |||||
| import { DvaModel } from 'umi'; | |||||
| export interface LoginModelState { | |||||
| list: any[]; | |||||
| info: any; | |||||
| visible: boolean; | |||||
| } | |||||
| const model: DvaModel<LoginModelState> = { | |||||
| namespace: 'loginModel', | |||||
| state: { | |||||
| list: [], | |||||
| info: {}, | |||||
| visible: false, | |||||
| }, | |||||
| reducers: { | |||||
| updateState(state, { payload }) { | |||||
| return { | |||||
| ...state, | |||||
| ...payload, | |||||
| }; | |||||
| }, | |||||
| }, | |||||
| effects: { | |||||
| *login({ payload = {} }, { call }) { | |||||
| const { data, response } = yield call(userService.login, payload); | |||||
| const { retcode, data: res } = data; | |||||
| const authorization = response.headers.get(Authorization); | |||||
| if (retcode === 0) { | |||||
| message.success(i18n.t('message.logged')); | |||||
| const token = res.access_token; | |||||
| const userInfo = { | |||||
| avatar: res.avatar, | |||||
| name: res.nickname, | |||||
| email: res.email, | |||||
| }; | |||||
| authorizationUtil.setItems({ | |||||
| Authorization: authorization, | |||||
| userInfo: JSON.stringify(userInfo), | |||||
| Token: token, | |||||
| }); | |||||
| } | |||||
| return retcode; | |||||
| }, | |||||
| *register({ payload = {} }, { call }) { | |||||
| const { data } = yield call(userService.register, payload); | |||||
| console.log(); | |||||
| const { retcode } = data; | |||||
| if (retcode === 0) { | |||||
| message.success(i18n.t('message.registered')); | |||||
| } | |||||
| return retcode; | |||||
| }, | |||||
| *logout({ payload = {} }, { call }) { | |||||
| const { data } = yield call(userService.logout, payload); | |||||
| const { retcode } = data; | |||||
| if (retcode === 0) { | |||||
| message.success(i18n.t('message.logout')); | |||||
| } | |||||
| return retcode; | |||||
| }, | |||||
| }, | |||||
| }; | |||||
| export default model; |
| import { Domain } from '@/constants/common'; | import { Domain } from '@/constants/common'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | |||||
| import { useLogout } from '@/hooks/login-hooks'; | |||||
| import { useSecondPathName } from '@/hooks/route-hook'; | import { useSecondPathName } from '@/hooks/route-hook'; | ||||
| import { useFetchSystemVersion } from '@/hooks/user-setting-hooks'; | |||||
| import type { MenuProps } from 'antd'; | import type { MenuProps } from 'antd'; | ||||
| import { Flex, Menu } from 'antd'; | import { Flex, Menu } from 'antd'; | ||||
| import React, { useEffect, useMemo } from 'react'; | import React, { useEffect, useMemo } from 'react'; | ||||
| UserSettingIconMap, | UserSettingIconMap, | ||||
| UserSettingRouteKey, | UserSettingRouteKey, | ||||
| } from '../constants'; | } from '../constants'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | |||||
| import { useFetchSystemVersion, useLogout } from '@/hooks/user-setting-hooks'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| type MenuItem = Required<MenuProps>['items'][number]; | type MenuItem = Required<MenuProps>['items'][number]; | ||||
| const SideBar = () => { | const SideBar = () => { | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const pathName = useSecondPathName(); | const pathName = useSecondPathName(); | ||||
| const logout = useLogout(); | |||||
| const { logout } = useLogout(); | |||||
| const { t } = useTranslate('setting'); | const { t } = useTranslate('setting'); | ||||
| const { version, fetchSystemVersion } = useFetchSystemVersion(); | const { version, fetchSystemVersion } = useFetchSystemVersion(); | ||||
| import { TestingModelState } from '@/pages/add-knowledge/components/knowledge-testing/model'; | import { TestingModelState } from '@/pages/add-knowledge/components/knowledge-testing/model'; | ||||
| import { kAModelState } from '@/pages/add-knowledge/model'; | import { kAModelState } from '@/pages/add-knowledge/model'; | ||||
| import { ChatModelState } from '@/pages/chat/model'; | import { ChatModelState } from '@/pages/chat/model'; | ||||
| import { LoginModelState } from '@/pages/login/model'; | |||||
| import { SettingModelState } from '@/pages/user-setting/model'; | import { SettingModelState } from '@/pages/user-setting/model'; | ||||
| declare module 'lodash'; | declare module 'lodash'; | ||||
| export interface RootState { | export interface RootState { | ||||
| chatModel: ChatModelState; | chatModel: ChatModelState; | ||||
| loginModel: LoginModelState; | |||||
| settingModel: SettingModelState; | settingModel: SettingModelState; | ||||
| kFModel: KFModelState; | kFModel: KFModelState; | ||||
| kAModel: kAModelState; | kAModel: kAModelState; |