127 lines
3.9 KiB
JavaScript
127 lines
3.9 KiB
JavaScript
import React, { useEffect, useState } from 'react'
|
|
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom'
|
|
import { useDispatch, useSelector } from 'react-redux'
|
|
import ConfigPanel from './components/ConfigPanel'
|
|
import ConfigGuide from './components/ConfigGuide'
|
|
import TradeList from './components/TradeList'
|
|
import StatsDashboard from './components/StatsDashboard'
|
|
import AdminDashboard from './components/AdminDashboard'
|
|
import Recommendations from './components/Recommendations'
|
|
import LogMonitor from './components/LogMonitor'
|
|
import AccountSelector from './components/AccountSelector'
|
|
import GlobalConfig from './components/GlobalConfig'
|
|
import Login from './components/Login'
|
|
import { api, clearAuthToken } from './services/api'
|
|
import {
|
|
setCurrentUser,
|
|
setUsers,
|
|
selectCurrentUser,
|
|
selectUsers,
|
|
selectIsAdmin,
|
|
} from './store/appSlice'
|
|
import './App.css'
|
|
|
|
function App() {
|
|
const dispatch = useDispatch()
|
|
const currentUser = useSelector(selectCurrentUser)
|
|
const isAdmin = useSelector(selectIsAdmin)
|
|
|
|
const [checking, setChecking] = useState(true)
|
|
|
|
const refreshMe = async () => {
|
|
try {
|
|
const u = await api.me()
|
|
dispatch(setCurrentUser(u))
|
|
|
|
// 不再加载用户列表,去掉用户切换功能
|
|
} catch (e) {
|
|
dispatch(setCurrentUser(null))
|
|
} finally {
|
|
setChecking(false)
|
|
}
|
|
}
|
|
|
|
|
|
useEffect(() => {
|
|
refreshMe()
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [])
|
|
|
|
if (checking) {
|
|
return (
|
|
<div className="app">
|
|
<div className="main-content" style={{ padding: '24px' }}>
|
|
正在初始化...
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (!currentUser) {
|
|
return <Login onLoggedIn={refreshMe} />
|
|
}
|
|
|
|
return (
|
|
<Router>
|
|
<div className="app">
|
|
<nav className="navbar">
|
|
<div className="nav-container">
|
|
<div className="nav-left">
|
|
<h1 className="nav-title">自动交易系统</h1>
|
|
{!isAdmin && <AccountSelector />}
|
|
</div>
|
|
<div className="nav-links">
|
|
<Link to="/">仪表板</Link>
|
|
{!isAdmin && (
|
|
<>
|
|
<Link to="/recommendations">交易推荐</Link>
|
|
<Link to="/config">配置</Link>
|
|
<Link to="/trades">交易记录</Link>
|
|
</>
|
|
)}
|
|
{isAdmin && (
|
|
<>
|
|
<Link to="/global-config">全局配置</Link>
|
|
<Link to="/logs">日志监控</Link>
|
|
</>
|
|
)}
|
|
</div>
|
|
<div className="nav-user">
|
|
<span className="nav-user-name">
|
|
{currentUser?.username ? currentUser.username : 'user'}
|
|
{isAdmin ? '(管理员)' : ''}
|
|
</span>
|
|
<button
|
|
type="button"
|
|
className="nav-logout"
|
|
onClick={() => {
|
|
clearAuthToken()
|
|
dispatch(setCurrentUser(null))
|
|
dispatch(setUsers([]))
|
|
setChecking(false)
|
|
}}
|
|
>
|
|
退出
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<main className="main-content">
|
|
<Routes>
|
|
<Route path="/" element={isAdmin ? <AdminDashboard /> : <StatsDashboard />} />
|
|
<Route path="/recommendations" element={<Recommendations />} />
|
|
<Route path="/config" element={<ConfigPanel />} />
|
|
<Route path="/config/guide" element={<ConfigGuide />} />
|
|
<Route path="/trades" element={<TradeList />} />
|
|
<Route path="/global-config" element={isAdmin ? <GlobalConfig /> : <div style={{ padding: '24px' }}>无权限</div>} />
|
|
<Route path="/logs" element={isAdmin ? <LogMonitor /> : <div style={{ padding: '24px' }}>无权限</div>} />
|
|
</Routes>
|
|
</main>
|
|
</div>
|
|
</Router>
|
|
)
|
|
}
|
|
|
|
export default App
|