feat: save login token to localStorage for test
This commit is contained in:
parent
b951e34206
commit
6f6e6997ad
@ -5,6 +5,7 @@ const AppConfig = {
|
|||||||
API_PREFIX: 'http://chat.wx.wm-app.xyz',
|
API_PREFIX: 'http://chat.wx.wm-app.xyz',
|
||||||
DEPLOY_DIR: '/',
|
DEPLOY_DIR: '/',
|
||||||
PUBLIC_PATH: '/',
|
PUBLIC_PATH: '/',
|
||||||
|
LOGIN_TOKEN_KEY: 'chat.user.token',
|
||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
CLIENT_ID: 'uziRFTVYkcgnGjAx',
|
CLIENT_ID: 'uziRFTVYkcgnGjAx',
|
||||||
@ -12,6 +13,7 @@ const AppConfig = {
|
|||||||
API_PREFIX: 'http://chat.wx.wm-app.xyz',
|
API_PREFIX: 'http://chat.wx.wm-app.xyz',
|
||||||
DEPLOY_DIR: (process.env.DEPLOY_DIR || '/'),
|
DEPLOY_DIR: (process.env.DEPLOY_DIR || '/'),
|
||||||
PUBLIC_PATH: (process.env.PUBLIC_PATH || './'),
|
PUBLIC_PATH: (process.env.PUBLIC_PATH || './'),
|
||||||
|
LOGIN_TOKEN_KEY: 'chat.user.token',
|
||||||
},
|
},
|
||||||
production: {
|
production: {
|
||||||
CLIENT_ID: 'aVjsh87iWEuhZdWC',
|
CLIENT_ID: 'aVjsh87iWEuhZdWC',
|
||||||
@ -19,6 +21,7 @@ const AppConfig = {
|
|||||||
API_PREFIX: 'http://chat.wx.wm-app.xyz',
|
API_PREFIX: 'http://chat.wx.wm-app.xyz',
|
||||||
DEPLOY_DIR: (process.env.DEPLOY_DIR || '/'),
|
DEPLOY_DIR: (process.env.DEPLOY_DIR || '/'),
|
||||||
PUBLIC_PATH: (process.env.PUBLIC_PATH || './'),
|
PUBLIC_PATH: (process.env.PUBLIC_PATH || './'),
|
||||||
|
LOGIN_TOKEN_KEY: 'chat.user.token',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default AppConfig
|
export default AppConfig
|
||||||
|
25
src/App.tsx
25
src/App.tsx
@ -1,10 +1,11 @@
|
|||||||
import React, {useEffect, useState} from 'react'
|
import React, {useEffect, useState} from 'react'
|
||||||
import Login from "./components/Login";
|
import Login from "./components/Login";
|
||||||
import {useSetState} from "ahooks";
|
import {useMount, useSetState} from "ahooks";
|
||||||
import {info, UserModel} from "./services/api";
|
import {info, UserModel} from "./services/api";
|
||||||
import Vip from "./components/vip";
|
import Vip from "./components/vip";
|
||||||
import Button from "./components/Button";
|
import Button from "./components/Button";
|
||||||
import {io} from 'socket.io-client'
|
import {io} from 'socket.io-client'
|
||||||
|
import { useEffectOnce } from './utils/useEffectOnce';
|
||||||
|
|
||||||
|
|
||||||
type MessageItem = {
|
type MessageItem = {
|
||||||
@ -14,7 +15,7 @@ type MessageItem = {
|
|||||||
content: string[];
|
content: string[];
|
||||||
avatar: string;
|
avatar: string;
|
||||||
}
|
}
|
||||||
|
const LOGIN_TOKEN_KEY = APP_CONFIG.LOGIN_TOKEN_KEY;
|
||||||
const avatar = 'https://www.cdnjson.com/images/2023/01/31/qwrgFf.jpg',
|
const avatar = 'https://www.cdnjson.com/images/2023/01/31/qwrgFf.jpg',
|
||||||
avatar1 = 'https://www.cdnjson.com/images/2023/02/25/AI.png',
|
avatar1 = 'https://www.cdnjson.com/images/2023/02/25/AI.png',
|
||||||
globalMessageList: MessageItem[] = [
|
globalMessageList: MessageItem[] = [
|
||||||
@ -29,8 +30,10 @@ const avatar = 'https://www.cdnjson.com/images/2023/01/31/qwrgFf.jpg',
|
|||||||
avatar: avatar1
|
avatar: avatar1
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
socket = io(APP_CONFIG.API_PREFIX, {
|
socket = io(APP_CONFIG.API_PREFIX, {
|
||||||
autoConnect: false
|
autoConnect: false,
|
||||||
|
path:`/socket.io`
|
||||||
})
|
})
|
||||||
let messageIndex = 5, lastMessage = 0, initSocket = false;
|
let messageIndex = 5, lastMessage = 0, initSocket = false;
|
||||||
|
|
||||||
@ -51,7 +54,7 @@ function App() {
|
|||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
//TODO 调用注销登录接口
|
//TODO 调用注销登录接口
|
||||||
localStorage.removeItem("chat-login")
|
localStorage.removeItem(LOGIN_TOKEN_KEY)
|
||||||
setState({user: undefined})
|
setState({user: undefined})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +91,7 @@ function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadUserInfo() {
|
function loadUserInfo() {
|
||||||
if (localStorage.getItem("chat-login")) {
|
if (!localStorage.getItem(LOGIN_TOKEN_KEY)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info().then(user => {
|
info().then(user => {
|
||||||
@ -147,7 +150,7 @@ function App() {
|
|||||||
})();
|
})();
|
||||||
};
|
};
|
||||||
// 监听
|
// 监听
|
||||||
useEffect(loadUserInfo, [])
|
useEffectOnce(loadUserInfo)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (messageList.length == 0) return;
|
if (messageList.length == 0) return;
|
||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
@ -203,16 +206,18 @@ function App() {
|
|||||||
</>)}
|
</>)}
|
||||||
</Button>
|
</Button>
|
||||||
{state.user?.vip &&
|
{state.user?.vip &&
|
||||||
<div className="open-vip" onClick={() => setState({showVip: true})}>+增加次数<</div>}
|
<div className="open-vip" onClick={() => setState({showVip: true})}>+ 增加次数 ></div>}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{state.showLogin && <Login
|
{state.showLogin && <Login
|
||||||
onClose={(logged) => {
|
onClose={(logged,data) => {
|
||||||
setState({showLogin: false})
|
setState({showLogin: false})
|
||||||
localStorage.setItem("chat-login", "yes")
|
if(logged && data){
|
||||||
logged && loadUserInfo()
|
localStorage.setItem(LOGIN_TOKEN_KEY, data.token)
|
||||||
|
loadUserInfo()
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>}
|
/>}
|
||||||
{state.showVip && <Vip onClose={(opened) => {
|
{state.showVip && <Vip onClose={(opened) => {
|
||||||
|
@ -4,10 +4,10 @@ import IconClose from "./icons/IconClose";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
import {useSetState, useCountDown} from "ahooks";
|
import {useSetState, useCountDown} from "ahooks";
|
||||||
import Checkbox from "./Checkbox";
|
import Checkbox from "./Checkbox";
|
||||||
import {login, sendCode} from "../services/api";
|
import {login, sendCode, UserModel} from "../services/api";
|
||||||
|
|
||||||
export type LoginProps = {
|
export type LoginProps = {
|
||||||
onClose: (logged?: boolean) => void
|
onClose: (logged?: boolean,user?: UserModel) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const Login: React.FC<LoginProps> = (props) => {
|
const Login: React.FC<LoginProps> = (props) => {
|
||||||
@ -45,8 +45,8 @@ const Login: React.FC<LoginProps> = (props) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setState({error: '', loginLoading: true})
|
setState({error: '', loginLoading: true})
|
||||||
login(data).then(() => {
|
login(data).then((ret) => {
|
||||||
props.onClose(true)
|
props.onClose(true,ret)
|
||||||
}).catch(error).finally(() => {
|
}).catch(error).finally(() => {
|
||||||
setState({
|
setState({
|
||||||
loginLoading: false
|
loginLoading: false
|
||||||
|
@ -11,10 +11,11 @@ export type UserModel = {
|
|||||||
export function login(data: any) {
|
export function login(data: any) {
|
||||||
return post<UserModel>('/api/user/login', data)
|
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) {
|
export function sendCode(phone: string) {
|
||||||
return post('/api/sendCode', {phone})
|
return post('/api/sendCode', {phone})
|
||||||
|
@ -15,17 +15,21 @@ const Axios = axios.create({
|
|||||||
baseURL: APP_CONFIG.API_PREFIX,
|
baseURL: APP_CONFIG.API_PREFIX,
|
||||||
timeout: 20000, // 设置超时时长
|
timeout: 20000, // 设置超时时长
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': JSON_FORMAT,
|
'Content-Type': JSON_FORMAT
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// 请求前拦截
|
// 请求前拦截
|
||||||
// Axios.interceptors.request.use(config => {
|
Axios.interceptors.request.use(config => {
|
||||||
// return config
|
const token = localStorage.getItem(APP_CONFIG.LOGIN_TOKEN_KEY)
|
||||||
// }, err => {
|
if (token) {
|
||||||
// return Promise.reject(err)
|
config.headers['token'] = token;
|
||||||
// })
|
}
|
||||||
|
return config
|
||||||
|
}, err => {
|
||||||
|
return Promise.reject(err)
|
||||||
|
})
|
||||||
//
|
//
|
||||||
// // 返回后拦截
|
// // 返回后拦截
|
||||||
// Axios.interceptors.response.use(res => {
|
// Axios.interceptors.response.use(res => {
|
||||||
|
27
src/utils/useEffectOnce.ts
Normal file
27
src/utils/useEffectOnce.ts
Normal 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()
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
}
|
1
src/vite-env.d.ts
vendored
1
src/vite-env.d.ts
vendored
@ -11,6 +11,7 @@ interface IAppConfigItem {
|
|||||||
* 静态资源目录
|
* 静态资源目录
|
||||||
*/
|
*/
|
||||||
PUBLIC_PATH?: string
|
PUBLIC_PATH?: string
|
||||||
|
LOGIN_TOKEN_KEY: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type IAPP_ENV = 'development' | 'test' | 'production'
|
type IAPP_ENV = 'development' | 'test' | 'production'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user