mirror of
https://github.com/woodchen-ink/nezha-dash-v1.git
synced 2025-07-18 09:31:55 +08:00
feat: sync login status with dashboard
This commit is contained in:
parent
97da6b43c1
commit
1c3684faaf
@ -140,14 +140,32 @@ function Links() {
|
|||||||
|
|
||||||
function DashboardLink() {
|
function DashboardLink() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { reconnect } = useWebSocketContext()
|
||||||
|
const initRef = useRef(false)
|
||||||
const { data: userData } = useQuery({
|
const { data: userData } = useQuery({
|
||||||
queryKey: ["login-user"],
|
queryKey: ["login-user"],
|
||||||
queryFn: () => fetchLoginUser(),
|
queryFn: () => fetchLoginUser(),
|
||||||
refetchOnMount: true,
|
refetchOnMount: true,
|
||||||
refetchOnWindowFocus: true,
|
refetchOnWindowFocus: true,
|
||||||
|
refetchIntervalInBackground: true,
|
||||||
refetchInterval: 1000 * 60 * 1,
|
refetchInterval: 1000 * 60 * 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let isLogin = !!userData?.data?.id
|
||||||
|
|
||||||
|
if (!document.cookie) {
|
||||||
|
isLogin = false
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// 当登录状态变化时重新连接 WebSocket
|
||||||
|
if (initRef.current) {
|
||||||
|
reconnect()
|
||||||
|
} else {
|
||||||
|
initRef.current = true
|
||||||
|
}
|
||||||
|
}, [isLogin])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<a
|
<a
|
||||||
@ -156,8 +174,8 @@ function DashboardLink() {
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="flex items-center text-nowrap gap-1 text-sm font-medium opacity-50 transition-opacity hover:opacity-100"
|
className="flex items-center text-nowrap gap-1 text-sm font-medium opacity-50 transition-opacity hover:opacity-100"
|
||||||
>
|
>
|
||||||
{!userData?.data?.id && t("login")}
|
{!isLogin && t("login")}
|
||||||
{userData?.data?.id && t("dashboard")}
|
{isLogin && t("dashboard")}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -4,10 +4,12 @@ export interface WebSocketContextType {
|
|||||||
lastMessage: { data: string } | null
|
lastMessage: { data: string } | null
|
||||||
connected: boolean
|
connected: boolean
|
||||||
messageHistory: { data: string }[]
|
messageHistory: { data: string }[]
|
||||||
|
reconnect: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WebSocketContext = createContext<WebSocketContextType>({
|
export const WebSocketContext = createContext<WebSocketContextType>({
|
||||||
lastMessage: null,
|
lastMessage: null,
|
||||||
connected: false,
|
connected: false,
|
||||||
messageHistory: [],
|
messageHistory: [],
|
||||||
|
reconnect: () => {},
|
||||||
})
|
})
|
||||||
|
@ -15,8 +15,37 @@ export const WebSocketProvider: React.FC<WebSocketProviderProps> = ({ url, child
|
|||||||
const reconnectTimeout = useRef<NodeJS.Timeout>(null)
|
const reconnectTimeout = useRef<NodeJS.Timeout>(null)
|
||||||
const maxReconnectAttempts = 30
|
const maxReconnectAttempts = 30
|
||||||
const reconnectAttempts = useRef(0)
|
const reconnectAttempts = useRef(0)
|
||||||
|
const isConnecting = useRef(false)
|
||||||
|
|
||||||
|
const cleanup = () => {
|
||||||
|
if (ws.current) {
|
||||||
|
// 移除所有事件监听器
|
||||||
|
ws.current.onopen = null
|
||||||
|
ws.current.onclose = null
|
||||||
|
ws.current.onmessage = null
|
||||||
|
ws.current.onerror = null
|
||||||
|
|
||||||
|
if (ws.current.readyState === WebSocket.OPEN || ws.current.readyState === WebSocket.CONNECTING) {
|
||||||
|
ws.current.close()
|
||||||
|
}
|
||||||
|
ws.current = null
|
||||||
|
}
|
||||||
|
if (reconnectTimeout.current) {
|
||||||
|
clearTimeout(reconnectTimeout.current)
|
||||||
|
reconnectTimeout.current = null
|
||||||
|
}
|
||||||
|
setConnected(false)
|
||||||
|
}
|
||||||
|
|
||||||
const connect = () => {
|
const connect = () => {
|
||||||
|
if (isConnecting.current) {
|
||||||
|
console.log("Connection already in progress")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup()
|
||||||
|
isConnecting.current = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const wsUrl = new URL(url, window.location.origin)
|
const wsUrl = new URL(url, window.location.origin)
|
||||||
wsUrl.protocol = wsUrl.protocol.replace("http", "ws")
|
wsUrl.protocol = wsUrl.protocol.replace("http", "ws")
|
||||||
@ -27,13 +56,15 @@ export const WebSocketProvider: React.FC<WebSocketProviderProps> = ({ url, child
|
|||||||
console.log("WebSocket connected")
|
console.log("WebSocket connected")
|
||||||
setConnected(true)
|
setConnected(true)
|
||||||
reconnectAttempts.current = 0
|
reconnectAttempts.current = 0
|
||||||
|
isConnecting.current = false
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.current.onclose = () => {
|
ws.current.onclose = () => {
|
||||||
console.log("WebSocket disconnected")
|
console.log("WebSocket disconnected")
|
||||||
setConnected(false)
|
setConnected(false)
|
||||||
|
ws.current = null
|
||||||
|
isConnecting.current = false
|
||||||
|
|
||||||
// 重连逻辑
|
|
||||||
if (reconnectAttempts.current < maxReconnectAttempts) {
|
if (reconnectAttempts.current < maxReconnectAttempts) {
|
||||||
reconnectTimeout.current = setTimeout(() => {
|
reconnectTimeout.current = setTimeout(() => {
|
||||||
reconnectAttempts.current++
|
reconnectAttempts.current++
|
||||||
@ -54,22 +85,28 @@ export const WebSocketProvider: React.FC<WebSocketProviderProps> = ({ url, child
|
|||||||
|
|
||||||
ws.current.onerror = (error) => {
|
ws.current.onerror = (error) => {
|
||||||
console.error("WebSocket error:", error)
|
console.error("WebSocket error:", error)
|
||||||
|
isConnecting.current = false
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("WebSocket connection error:", error)
|
console.error("WebSocket connection error:", error)
|
||||||
|
isConnecting.current = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const reconnect = () => {
|
||||||
|
reconnectAttempts.current = 0
|
||||||
|
// 等待一个小延时确保清理完成
|
||||||
|
cleanup()
|
||||||
|
setTimeout(() => {
|
||||||
|
connect()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
connect()
|
connect()
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (ws.current) {
|
cleanup()
|
||||||
ws.current.close()
|
|
||||||
}
|
|
||||||
if (reconnectTimeout.current) {
|
|
||||||
clearTimeout(reconnectTimeout.current)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [url])
|
}, [url])
|
||||||
|
|
||||||
@ -77,6 +114,7 @@ export const WebSocketProvider: React.FC<WebSocketProviderProps> = ({ url, child
|
|||||||
lastMessage,
|
lastMessage,
|
||||||
connected,
|
connected,
|
||||||
messageHistory, // 添加到 context value
|
messageHistory, // 添加到 context value
|
||||||
|
reconnect, // 添加到 context value
|
||||||
}
|
}
|
||||||
|
|
||||||
return <WebSocketContext.Provider value={contextValue}>{children}</WebSocketContext.Provider>
|
return <WebSocketContext.Provider value={contextValue}>{children}</WebSocketContext.Provider>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user