mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-19 19:04:23 +08:00
refactor: 拆分 sidebar 和内容区为独立组件
This commit is contained in:
+13
-103
@@ -1,18 +1,11 @@
|
|||||||
import { Layout, Menu, Space, Dialog, Input, Button, Tag, MessagePlugin } from 'tdesign-react'
|
import { Layout, Dialog, Input, MessagePlugin } from 'tdesign-react'
|
||||||
import { useEffect, useMemo, useState } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
import { UserIcon, SettingIcon, HistoryIcon, RootListIcon, ViewListIcon } from 'tdesign-icons-react'
|
import { HashRouter, useLocation, useNavigate } from 'react-router-dom'
|
||||||
import { HashRouter, Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom'
|
import { Sidebar } from './components/Sidebar'
|
||||||
import { StudentManager } from './components/StudentManager'
|
import { ContentArea } from './components/ContentArea'
|
||||||
import { Settings } from './components/Settings'
|
|
||||||
import { ReasonManager } from './components/ReasonManager'
|
|
||||||
import { ScoreManager } from './components/ScoreManager'
|
|
||||||
import { Leaderboard } from './components/Leaderboard'
|
|
||||||
import { SettlementHistory } from './components/SettlementHistory'
|
|
||||||
import { Wizard } from './components/Wizard'
|
import { Wizard } from './components/Wizard'
|
||||||
import { ThemeProvider } from './contexts/ThemeContext'
|
import { ThemeProvider } from './contexts/ThemeContext'
|
||||||
|
|
||||||
const { Header, Content, Aside } = Layout
|
|
||||||
|
|
||||||
function MainContent(): React.JSX.Element {
|
function MainContent(): React.JSX.Element {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
@@ -95,99 +88,16 @@ function MainContent(): React.JSX.Element {
|
|||||||
if (key === 'settings') navigate('/settings')
|
if (key === 'settings') navigate('/settings')
|
||||||
}
|
}
|
||||||
|
|
||||||
const permissionTag = (
|
|
||||||
<Tag
|
|
||||||
theme={permission === 'admin' ? 'success' : permission === 'points' ? 'warning' : 'default'}
|
|
||||||
variant="light"
|
|
||||||
>
|
|
||||||
{permission === 'admin' ? '管理权限' : permission === 'points' ? '积分权限' : '只读'}
|
|
||||||
</Tag>
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout style={{ height: '100vh', backgroundColor: 'var(--ss-bg-color)' }}>
|
<Layout style={{ height: '100vh', flexDirection: 'row', overflow: 'hidden' }}>
|
||||||
<Aside
|
<Sidebar activeMenu={activeMenu} permission={permission} onMenuChange={onMenuChange} />
|
||||||
className="ss-sidebar"
|
<ContentArea
|
||||||
style={{
|
permission={permission}
|
||||||
backgroundColor: 'var(--ss-sidebar-bg)',
|
hasAnyPassword={hasAnyPassword}
|
||||||
borderRight: '1px solid var(--ss-border-color)'
|
onAuthClick={() => setAuthVisible(true)}
|
||||||
}}
|
onLogout={logout}
|
||||||
>
|
/>
|
||||||
<div style={{ padding: '24px', textAlign: 'center' }}>
|
|
||||||
<h2 style={{ color: 'var(--ss-sidebar-text, var(--ss-text-main))', margin: 0 }}>
|
|
||||||
SecScore
|
|
||||||
</h2>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
fontSize: '12px',
|
|
||||||
color: 'var(--ss-sidebar-text, var(--ss-text-main))'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
教育积分管理
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Menu value={activeMenu} onChange={onMenuChange} style={{ width: '100%', border: 'none' }}>
|
|
||||||
<Menu.MenuItem value="students" icon={<UserIcon />} disabled={permission !== 'admin'}>
|
|
||||||
学生管理
|
|
||||||
</Menu.MenuItem>
|
|
||||||
<Menu.MenuItem value="score" icon={<HistoryIcon />}>
|
|
||||||
积分管理
|
|
||||||
</Menu.MenuItem>
|
|
||||||
<Menu.MenuItem value="leaderboard" icon={<ViewListIcon />}>
|
|
||||||
排行榜
|
|
||||||
</Menu.MenuItem>
|
|
||||||
<Menu.MenuItem value="settlements" icon={<HistoryIcon />}>
|
|
||||||
结算历史
|
|
||||||
</Menu.MenuItem>
|
|
||||||
<Menu.MenuItem value="reasons" icon={<RootListIcon />} disabled={permission !== 'admin'}>
|
|
||||||
理由管理
|
|
||||||
</Menu.MenuItem>
|
|
||||||
<Menu.MenuItem value="settings" icon={<SettingIcon />} disabled={permission !== 'admin'}>
|
|
||||||
系统设置
|
|
||||||
</Menu.MenuItem>
|
|
||||||
</Menu>
|
|
||||||
</Aside>
|
|
||||||
<Layout>
|
|
||||||
<Header
|
|
||||||
style={{
|
|
||||||
backgroundColor: 'var(--ss-header-bg)',
|
|
||||||
borderBottom: '1px solid var(--ss-border-color)',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'flex-end',
|
|
||||||
padding: '0 24px'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Space>
|
|
||||||
{permissionTag}
|
|
||||||
{hasAnyPassword && (
|
|
||||||
<>
|
|
||||||
<Button size="small" variant="outline" onClick={() => setAuthVisible(true)}>
|
|
||||||
输入密码
|
|
||||||
</Button>
|
|
||||||
<Button size="small" variant="outline" theme="danger" onClick={logout}>
|
|
||||||
锁定
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Space>
|
|
||||||
</Header>
|
|
||||||
<Content style={{ overflowY: 'auto' }}>
|
|
||||||
<Routes>
|
|
||||||
<Route path="/" element={<Navigate to="/score" replace />} />
|
|
||||||
<Route path="/students" element={<StudentManager canEdit={permission === 'admin'} />} />
|
|
||||||
<Route
|
|
||||||
path="/score"
|
|
||||||
element={<ScoreManager canEdit={permission === 'admin' || permission === 'points'} />}
|
|
||||||
/>
|
|
||||||
<Route path="/leaderboard" element={<Leaderboard />} />
|
|
||||||
<Route path="/settlements" element={<SettlementHistory />} />
|
|
||||||
<Route path="/reasons" element={<ReasonManager canEdit={permission === 'admin'} />} />
|
|
||||||
<Route path="/settings" element={<Settings permission={permission} />} />
|
|
||||||
<Route path="*" element={<Navigate to="/score" replace />} />
|
|
||||||
</Routes>
|
|
||||||
</Content>
|
|
||||||
</Layout>
|
|
||||||
<Wizard visible={wizardVisible} onComplete={() => setWizardVisible(false)} />
|
<Wizard visible={wizardVisible} onComplete={() => setWizardVisible(false)} />
|
||||||
|
|
||||||
<Dialog
|
<Dialog
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import { Layout, Space, Button, Tag } from 'tdesign-react'
|
||||||
|
import { Routes, Route, Navigate } from 'react-router-dom'
|
||||||
|
import { StudentManager } from './StudentManager'
|
||||||
|
import { Settings } from './Settings'
|
||||||
|
import { ReasonManager } from './ReasonManager'
|
||||||
|
import { ScoreManager } from './ScoreManager'
|
||||||
|
import { Leaderboard } from './Leaderboard'
|
||||||
|
import { SettlementHistory } from './SettlementHistory'
|
||||||
|
import { WindowControls } from './WindowControls'
|
||||||
|
|
||||||
|
const { Content } = Layout
|
||||||
|
|
||||||
|
interface ContentAreaProps {
|
||||||
|
permission: 'admin' | 'points' | 'view'
|
||||||
|
hasAnyPassword: boolean
|
||||||
|
onAuthClick: () => void
|
||||||
|
onLogout: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ContentArea({
|
||||||
|
permission,
|
||||||
|
hasAnyPassword,
|
||||||
|
onAuthClick,
|
||||||
|
onLogout
|
||||||
|
}: ContentAreaProps): React.JSX.Element {
|
||||||
|
const permissionTag = (
|
||||||
|
<Tag
|
||||||
|
theme={permission === 'admin' ? 'success' : permission === 'points' ? 'warning' : 'default'}
|
||||||
|
variant="light"
|
||||||
|
>
|
||||||
|
{permission === 'admin' ? '管理权限' : permission === 'points' ? '积分权限' : '只读'}
|
||||||
|
</Tag>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
backgroundColor: 'var(--ss-bg-color)'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
height: '32px',
|
||||||
|
WebkitAppRegion: 'drag',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: 'var(--ss-header-bg)',
|
||||||
|
borderBottom: '1px solid var(--ss-border-color)',
|
||||||
|
flexShrink: 0
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div style={{ flex: 1 }} />
|
||||||
|
<div
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingRight: '0px',
|
||||||
|
WebkitAppRegion: 'no-drag'
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Space size="small" style={{ marginRight: '12px' }}>
|
||||||
|
{permissionTag}
|
||||||
|
{hasAnyPassword && (
|
||||||
|
<>
|
||||||
|
<Button size="small" variant="outline" onClick={onAuthClick}>
|
||||||
|
输入密码
|
||||||
|
</Button>
|
||||||
|
<Button size="small" variant="outline" theme="danger" onClick={onLogout}>
|
||||||
|
锁定
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
<WindowControls />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Content style={{ flex: 1, overflowY: 'auto' }}>
|
||||||
|
<Routes>
|
||||||
|
<Route path="/" element={<Navigate to="/score" replace />} />
|
||||||
|
<Route path="/students" element={<StudentManager canEdit={permission === 'admin'} />} />
|
||||||
|
<Route
|
||||||
|
path="/score"
|
||||||
|
element={<ScoreManager canEdit={permission === 'admin' || permission === 'points'} />}
|
||||||
|
/>
|
||||||
|
<Route path="/leaderboard" element={<Leaderboard />} />
|
||||||
|
<Route path="/settlements" element={<SettlementHistory />} />
|
||||||
|
<Route path="/reasons" element={<ReasonManager canEdit={permission === 'admin'} />} />
|
||||||
|
<Route path="/settings" element={<Settings permission={permission} />} />
|
||||||
|
<Route path="*" element={<Navigate to="/score" replace />} />
|
||||||
|
</Routes>
|
||||||
|
</Content>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
import { Layout, Menu } from 'tdesign-react'
|
||||||
|
import { UserIcon, SettingIcon, HistoryIcon, RootListIcon, ViewListIcon } from 'tdesign-icons-react'
|
||||||
|
import appLogo from '../assets/logo.svg'
|
||||||
|
|
||||||
|
const { Aside } = Layout
|
||||||
|
|
||||||
|
interface SidebarProps {
|
||||||
|
activeMenu: string
|
||||||
|
permission: 'admin' | 'points' | 'view'
|
||||||
|
onMenuChange: (value: string | number) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Sidebar({ activeMenu, permission, onMenuChange }: SidebarProps): React.JSX.Element {
|
||||||
|
return (
|
||||||
|
<Aside
|
||||||
|
className="ss-sidebar"
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'var(--ss-sidebar-bg)',
|
||||||
|
borderRight: '1px solid var(--ss-border-color)',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
padding: '32px 24px 16px',
|
||||||
|
textAlign: 'center',
|
||||||
|
WebkitAppRegion: 'drag',
|
||||||
|
userSelect: 'none',
|
||||||
|
flexShrink: 0
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={appLogo}
|
||||||
|
style={{ width: '48px', height: '48px', marginBottom: '12px' }}
|
||||||
|
alt="logo"
|
||||||
|
/>
|
||||||
|
<h2
|
||||||
|
style={{
|
||||||
|
color: 'var(--ss-sidebar-text, var(--ss-text-main))',
|
||||||
|
margin: 0,
|
||||||
|
fontSize: '20px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
SecScore
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: '12px',
|
||||||
|
color: 'var(--ss-sidebar-text, var(--ss-text-main))',
|
||||||
|
opacity: 0.8,
|
||||||
|
marginTop: '4px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
教育积分管理
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<Menu value={activeMenu} onChange={onMenuChange} style={{ width: '100%', border: 'none' }}>
|
||||||
|
<Menu.MenuItem value="students" icon={<UserIcon />} disabled={permission !== 'admin'}>
|
||||||
|
学生管理
|
||||||
|
</Menu.MenuItem>
|
||||||
|
<Menu.MenuItem value="score" icon={<HistoryIcon />}>
|
||||||
|
积分管理
|
||||||
|
</Menu.MenuItem>
|
||||||
|
<Menu.MenuItem value="leaderboard" icon={<ViewListIcon />}>
|
||||||
|
排行榜
|
||||||
|
</Menu.MenuItem>
|
||||||
|
<Menu.MenuItem value="settlements" icon={<HistoryIcon />}>
|
||||||
|
结算历史
|
||||||
|
</Menu.MenuItem>
|
||||||
|
<Menu.MenuItem value="reasons" icon={<RootListIcon />} disabled={permission !== 'admin'}>
|
||||||
|
理由管理
|
||||||
|
</Menu.MenuItem>
|
||||||
|
<Menu.MenuItem value="settings" icon={<SettingIcon />} disabled={permission !== 'admin'}>
|
||||||
|
系统设置
|
||||||
|
</Menu.MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
</Aside>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user