mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-08 02:15:27 +08:00
feat: add ETag cache optimization, code-split WebUI, and refactor XML tool scanner
- Chat history: early 304 via Revision()/DetailRevision() to avoid full snapshot reads - WebUI: lazy-load tab containers with Suspense fallback - Toolstream: split tool_sieve_xml.go into tags.go and scan.go - CI: trigger on main branch, guard cross-build to dev/main pushes only - Docs: add DEVELOPER.md developer quick reference Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { Suspense, lazy, useCallback, useEffect, useState } from 'react'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import {
|
||||
LayoutDashboard,
|
||||
@@ -11,20 +11,33 @@ import {
|
||||
Server,
|
||||
Users,
|
||||
Globe,
|
||||
History
|
||||
History,
|
||||
Loader2
|
||||
} from 'lucide-react'
|
||||
import clsx from 'clsx'
|
||||
|
||||
import AccountManagerContainer from '../features/account/AccountManagerContainer'
|
||||
import ApiTesterContainer from '../features/apiTester/ApiTesterContainer'
|
||||
import ChatHistoryContainer from '../features/chatHistory/ChatHistoryContainer'
|
||||
import BatchImport from '../components/BatchImport'
|
||||
import VercelSyncContainer from '../features/vercel/VercelSyncContainer'
|
||||
import SettingsContainer from '../features/settings/SettingsContainer'
|
||||
import ProxyManagerContainer from '../features/proxy/ProxyManagerContainer'
|
||||
import LanguageToggle from '../components/LanguageToggle'
|
||||
import { useI18n } from '../i18n'
|
||||
|
||||
const AccountManagerContainer = lazy(() => import('../features/account/AccountManagerContainer'))
|
||||
const ApiTesterContainer = lazy(() => import('../features/apiTester/ApiTesterContainer'))
|
||||
const ChatHistoryContainer = lazy(() => import('../features/chatHistory/ChatHistoryContainer'))
|
||||
const BatchImport = lazy(() => import('../components/BatchImport'))
|
||||
const VercelSyncContainer = lazy(() => import('../features/vercel/VercelSyncContainer'))
|
||||
const SettingsContainer = lazy(() => import('../features/settings/SettingsContainer'))
|
||||
const ProxyManagerContainer = lazy(() => import('../features/proxy/ProxyManagerContainer'))
|
||||
|
||||
function TabLoadingFallback({ label }) {
|
||||
return (
|
||||
<div className="min-h-[320px] rounded-lg border border-border bg-card flex items-center justify-center">
|
||||
<div className="flex items-center gap-3 text-sm text-muted-foreground">
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
<span>{label}</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function DashboardShell({ token, onLogout, config, fetchConfig, showMessage, message, onForceLogout, isVercel }) {
|
||||
const { t } = useI18n()
|
||||
const location = useLocation()
|
||||
@@ -47,6 +60,7 @@ export default function DashboardShell({ token, onLogout, config, fetchConfig, s
|
||||
const pathTab = routeSegments[0] || ''
|
||||
const activeTab = tabIds.has(pathTab) ? pathTab : 'accounts'
|
||||
const adminBasePath = pathSegments[0] === 'admin' ? '/admin' : ''
|
||||
const activeNavItem = navItems.find(n => n.id === activeTab)
|
||||
|
||||
const navigateToTab = useCallback((tabID) => {
|
||||
const nextPath = tabID === 'accounts'
|
||||
@@ -232,10 +246,10 @@ export default function DashboardShell({ token, onLogout, config, fetchConfig, s
|
||||
<div className="max-w-6xl mx-auto space-y-4 lg:space-y-6">
|
||||
<div className="hidden lg:block mb-8">
|
||||
<h1 className="text-3xl font-bold tracking-tight mb-2">
|
||||
{navItems.find(n => n.id === activeTab)?.label}
|
||||
{activeNavItem?.label}
|
||||
</h1>
|
||||
<p className="text-muted-foreground">
|
||||
{navItems.find(n => n.id === activeTab)?.description}
|
||||
{activeNavItem?.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -251,7 +265,9 @@ export default function DashboardShell({ token, onLogout, config, fetchConfig, s
|
||||
)}
|
||||
|
||||
<div className="animate-in fade-in duration-500">
|
||||
{renderTab()}
|
||||
<Suspense fallback={<TabLoadingFallback label={activeNavItem?.label || 'DS2API'} />}>
|
||||
{renderTab()}
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user