feat: save login token to localStorage for test

This commit is contained in:
LittleBoy 2023-02-27 21:45:44 +08:00
parent b951e34206
commit 6f6e6997ad
7 changed files with 65 additions and 24 deletions

View File

@ -5,6 +5,7 @@ const AppConfig = {
API_PREFIX: 'http://chat.wx.wm-app.xyz',
DEPLOY_DIR: '/',
PUBLIC_PATH: '/',
LOGIN_TOKEN_KEY: 'chat.user.token',
},
test: {
CLIENT_ID: 'uziRFTVYkcgnGjAx',
@ -12,6 +13,7 @@ const AppConfig = {
API_PREFIX: 'http://chat.wx.wm-app.xyz',
DEPLOY_DIR: (process.env.DEPLOY_DIR || '/'),
PUBLIC_PATH: (process.env.PUBLIC_PATH || './'),
LOGIN_TOKEN_KEY: 'chat.user.token',
},
production: {
CLIENT_ID: 'aVjsh87iWEuhZdWC',
@ -19,6 +21,7 @@ const AppConfig = {
API_PREFIX: 'http://chat.wx.wm-app.xyz',
DEPLOY_DIR: (process.env.DEPLOY_DIR || '/'),
PUBLIC_PATH: (process.env.PUBLIC_PATH || './'),
LOGIN_TOKEN_KEY: 'chat.user.token',
}
}
export default AppConfig

View File

@ -1,10 +1,11 @@
import React, {useEffect, useState} from 'react'
import Login from "./components/Login";
import {useSetState} from "ahooks";
import {useMount, useSetState} from "ahooks";
import {info, UserModel} from "./services/api";
import Vip from "./components/vip";
import Button from "./components/Button";
import {io} from 'socket.io-client'
import { useEffectOnce } from './utils/useEffectOnce';
type MessageItem = {
@ -14,7 +15,7 @@ type MessageItem = {
content: string[];
avatar: string;
}
const LOGIN_TOKEN_KEY = APP_CONFIG.LOGIN_TOKEN_KEY;
const avatar = 'https://www.cdnjson.com/images/2023/01/31/qwrgFf.jpg',
avatar1 = 'https://www.cdnjson.com/images/2023/02/25/AI.png',
globalMessageList: MessageItem[] = [
@ -29,8 +30,10 @@ const avatar = 'https://www.cdnjson.com/images/2023/01/31/qwrgFf.jpg',
avatar: avatar1
},
],
socket = io(APP_CONFIG.API_PREFIX, {
autoConnect: false
autoConnect: false,
path:`/socket.io`
})
let messageIndex = 5, lastMessage = 0, initSocket = false;
@ -51,7 +54,7 @@ function App() {
function logout() {
//TODO 调用注销登录接口
localStorage.removeItem("chat-login")
localStorage.removeItem(LOGIN_TOKEN_KEY)
setState({user: undefined})
}
@ -88,7 +91,7 @@ function App() {
}
function loadUserInfo() {
if (localStorage.getItem("chat-login")) {
if (!localStorage.getItem(LOGIN_TOKEN_KEY)) {
return;
}
info().then(user => {
@ -147,7 +150,7 @@ function App() {
})();
};
// 监听
useEffect(loadUserInfo, [])
useEffectOnce(loadUserInfo)
useEffect(() => {
if (messageList.length == 0) return;
scrollToBottom();
@ -203,16 +206,18 @@ function App() {
</>)}
</Button>
{state.user?.vip &&
<div className="open-vip" onClick={() => setState({showVip: true})}>+&lt;</div>}
<div className="open-vip" onClick={() => setState({showVip: true})}>+ &gt;</div>}
</div>
</form>
</div>
</div>
{state.showLogin && <Login
onClose={(logged) => {
onClose={(logged,data) => {
setState({showLogin: false})
localStorage.setItem("chat-login", "yes")
logged && loadUserInfo()
if(logged && data){
localStorage.setItem(LOGIN_TOKEN_KEY, data.token)
loadUserInfo()
}
}}
/>}
{state.showVip && <Vip onClose={(opened) => {

View File

@ -4,10 +4,10 @@ import IconClose from "./icons/IconClose";
import Button from "./Button";
import {useSetState, useCountDown} from "ahooks";
import Checkbox from "./Checkbox";
import {login, sendCode} from "../services/api";
import {login, sendCode, UserModel} from "../services/api";
export type LoginProps = {
onClose: (logged?: boolean) => void
onClose: (logged?: boolean,user?: UserModel) => void
}
const Login: React.FC<LoginProps> = (props) => {
@ -45,8 +45,8 @@ const Login: React.FC<LoginProps> = (props) => {
return;
}
setState({error: '', loginLoading: true})
login(data).then(() => {
props.onClose(true)
login(data).then((ret) => {
props.onClose(true,ret)
}).catch(error).finally(() => {
setState({
loginLoading: false

View File

@ -11,10 +11,11 @@ export type UserModel = {
export function login(data: any) {
return post<UserModel>('/api/user/login', data)
}
export function info() {
return get<UserModel>('/api/user/info')
}
export function info() {
const token = localStorage.getItem(APP_CONFIG.LOGIN_TOKEN_KEY)
return post<UserModel>('/api/user/info', {token})
}
export function sendCode(phone: string) {
return post('/api/sendCode', {phone})

View File

@ -15,17 +15,21 @@ const Axios = axios.create({
baseURL: APP_CONFIG.API_PREFIX,
timeout: 20000, // 设置超时时长
headers: {
'Content-Type': JSON_FORMAT,
'Content-Type': JSON_FORMAT
}
})
// 请求前拦截
// Axios.interceptors.request.use(config => {
// return config
// }, err => {
// return Promise.reject(err)
// })
Axios.interceptors.request.use(config => {
const token = localStorage.getItem(APP_CONFIG.LOGIN_TOKEN_KEY)
if (token) {
config.headers['token'] = token;
}
return config
}, err => {
return Promise.reject(err)
})
//
// // 返回后拦截
// Axios.interceptors.response.use(res => {

View File

@ -0,0 +1,27 @@
import {useEffect, useRef, useState} from "react"
export function useEffectOnce(effect:Function) {
const effectFn = useRef(effect)
const destroyFn = useRef<Function>()
const effectCalled = useRef(false)
const rendered = useRef(false)
const [, refresh] = useState(0)
if (effectCalled.current) {
rendered.current = true
}
useEffect(() => {
if (!effectCalled.current) {
destroyFn.current = effectFn.current()
effectCalled.current = true
}
refresh(1)
return () => {
if (rendered.current === false) return
if (destroyFn.current) destroyFn.current()
}
}, [])
}

3
src/vite-env.d.ts vendored
View File

@ -11,6 +11,7 @@ interface IAppConfigItem {
*
*/
PUBLIC_PATH?: string
LOGIN_TOKEN_KEY: string
}
type IAPP_ENV = 'development' | 'test' | 'production'
@ -19,4 +20,4 @@ type IAppConfig = {
};
// 常量配置类型
declare const APP_ENV: IAPP_ENV;
declare const APP_CONFIG: IAppConfigItem;
declare const APP_CONFIG: IAppConfigItem;