release: v1.0.7

This commit is contained in:
MengMengCode
2026-06-06 11:17:57 +08:00
parent 28f81a8f1c
commit 21b87d3d56
15 changed files with 336 additions and 70 deletions
+71 -28
View File
@@ -1,3 +1,4 @@
import { useEffect, useState } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import {
ChevronLeft,
@@ -6,15 +7,19 @@ import {
Camera,
LayoutDashboard,
LogOut,
Moon,
Package,
Route,
ScrollText,
Server,
Settings2,
ShieldAlert,
Sun,
UserCog,
} from 'lucide-react'
import { useAuth } from '../contexts/AuthContext'
import { useTheme } from '../contexts/ThemeContext'
import { getVersion } from '../services/api'
import AppIcon from './AppIcon'
interface SidebarProps {
@@ -26,6 +31,18 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
const navigate = useNavigate()
const location = useLocation()
const { logout, isSubUser } = useAuth()
const { theme, toggleTheme } = useTheme()
const [version, setVersion] = useState('')
useEffect(() => {
getVersion()
.then(res => {
if (res.data?.data?.version) {
setVersion(res.data.data.version)
}
})
.catch(() => {})
}, [])
const isContainerPage =
location.pathname.startsWith('/containers') ||
@@ -42,27 +59,27 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
return (
<aside
className={`fixed left-0 top-0 h-full bg-white border-r border-gray-200 flex flex-col transition-all duration-300 z-30 ${
className={`fixed left-0 top-0 h-full bg-white border-r border-gray-200 flex flex-col transition-all duration-300 z-30 dark:bg-gray-900 dark:border-gray-700 ${
collapsed ? 'w-16' : 'w-60'
}`}
>
<div className="flex items-center justify-between h-14 px-4 border-b border-gray-200">
<div className="flex items-center justify-between h-14 px-4 border-b border-gray-200 dark:border-gray-700">
{!collapsed && (
<div className="flex items-center gap-2">
<div className="w-7 h-7 bg-gray-100 rounded flex items-center justify-center">
<div className="w-7 h-7 bg-gray-100 rounded flex items-center justify-center dark:bg-gray-800">
<AppIcon className="w-5 h-5" />
</div>
<span className="font-bold text-black text-sm">CLICD</span>
<span className="font-bold text-black text-sm dark:text-white">CLICD</span>
</div>
)}
{collapsed && (
<div className="w-7 h-7 bg-gray-100 rounded flex items-center justify-center mx-auto">
<div className="w-7 h-7 bg-gray-100 rounded flex items-center justify-center mx-auto dark:bg-gray-800">
<AppIcon className="w-5 h-5" />
</div>
)}
<button
onClick={onToggle}
className="p-1 rounded hover:bg-gray-100 text-gray-500"
className="p-1 rounded hover:bg-gray-100 text-gray-500 dark:hover:bg-gray-800 dark:text-gray-400"
title="切换侧边栏"
>
{collapsed ? (
@@ -79,8 +96,8 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
onClick={() => navigate('/')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
location.pathname === '/'
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
? 'bg-black text-white dark:bg-white dark:text-black'
: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
}`}
>
<LayoutDashboard className="w-4 h-4" />
@@ -92,8 +109,8 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
onClick={() => navigate('/containers')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
isContainerPage
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
? 'bg-black text-white dark:bg-white dark:text-black'
: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
}`}
>
<Server className="w-4 h-4" />
@@ -105,8 +122,8 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
onClick={() => navigate('/images')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
isImagesPage
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
? 'bg-black text-white dark:bg-white dark:text-black'
: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
}`}
>
<Package className="w-4 h-4" />
@@ -120,8 +137,8 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
onClick={() => navigate('/oversell')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
isOversellPage
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
? 'bg-black text-white dark:bg-white dark:text-black'
: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
}`}
>
<Settings2 className="w-4 h-4" />
@@ -132,8 +149,8 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
onClick={() => navigate('/security')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
isSecurityPage
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
? 'bg-black text-white dark:bg-white dark:text-black'
: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
}`}
>
<ShieldAlert className="w-4 h-4" />
@@ -144,8 +161,8 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
onClick={() => navigate('/snapshots')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
isSnapshotsPage
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
? 'bg-black text-white dark:bg-white dark:text-black'
: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
}`}
>
<Camera className="w-4 h-4" />
@@ -156,8 +173,8 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
onClick={() => navigate('/routing')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
isRoutingPage
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
? 'bg-black text-white dark:bg-white dark:text-black'
: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
}`}
>
<Route className="w-4 h-4" />
@@ -168,8 +185,8 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
onClick={() => navigate('/audit-logs')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
isAuditLogsPage
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
? 'bg-black text-white dark:bg-white dark:text-black'
: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
}`}
>
<ScrollText className="w-4 h-4" />
@@ -180,8 +197,8 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
onClick={() => navigate('/api-integration')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
isApiIntegrationPage
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
? 'bg-black text-white dark:bg-white dark:text-black'
: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
}`}
>
<Code2 className="w-4 h-4" />
@@ -192,8 +209,8 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
onClick={() => navigate('/settings')}
className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm transition-colors ${
isSettingsPage
? 'bg-black text-white'
: 'text-gray-700 hover:bg-gray-100'
? 'bg-black text-white dark:bg-white dark:text-black'
: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800'
}`}
>
<UserCog className="w-4 h-4" />
@@ -203,10 +220,36 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
)}
</nav>
<div className="border-t border-gray-200 p-2">
<div className="border-t border-gray-200 dark:border-gray-700 p-2 space-y-1">
{/* Theme Toggle */}
<button
onClick={toggleTheme}
className="w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm text-gray-600 hover:bg-gray-100 transition-colors dark:text-gray-400 dark:hover:bg-gray-800"
title={theme === 'dark' ? '切换亮色模式' : '切换暗黑模式'}
>
{theme === 'dark' ? (
<Sun className="w-4 h-4" />
) : (
<Moon className="w-4 h-4" />
)}
{!collapsed && <span>{theme === 'dark' ? '亮色模式' : '暗黑模式'}</span>}
</button>
{/* Version */}
{version && (
<div className={`px-3 py-2 text-xs text-gray-400 dark:text-gray-500 ${collapsed ? 'text-center' : ''}`}>
{collapsed ? (
<span title={`v${version}`}>v{version.split('.').slice(0, 2).join('.')}</span>
) : (
<span>v{version}</span>
)}
</div>
)}
{/* Logout */}
<button
onClick={logout}
className="w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm text-gray-600 hover:bg-gray-100 transition-colors"
className="w-full flex items-center gap-3 px-3 py-2.5 rounded-md text-sm text-gray-600 hover:bg-gray-100 transition-colors dark:text-gray-400 dark:hover:bg-gray-800"
>
<LogOut className="w-4 h-4" />
{!collapsed && <span>退</span>}