104 lines
3.2 KiB
TypeScript
104 lines
3.2 KiB
TypeScript
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
|
|
import { useEffect, useMemo, useState } from 'react';
|
|
|
|
import type { QuickActionType } from '../data/mockData';
|
|
import { QuickActionModal } from '../components/modals/QuickActionModal';
|
|
import { LoginModal } from '../components/modals/LoginModal';
|
|
import { Sidebar, type SectionKey } from '../components/layout/Sidebar';
|
|
import { TopBar } from '../components/layout/TopBar';
|
|
|
|
export interface MainLayoutContext {
|
|
search: string;
|
|
setSearch: (value: string) => void;
|
|
}
|
|
|
|
const sectionToRoute: Record<SectionKey, string> = {
|
|
home: '/home',
|
|
exam: '/exam',
|
|
booking: '/booking',
|
|
support: '/support',
|
|
};
|
|
|
|
const routeToSection = Object.entries(sectionToRoute).reduce<Record<string, SectionKey>>(
|
|
(acc, [section, route]) => {
|
|
acc[route] = section as SectionKey;
|
|
return acc;
|
|
},
|
|
{},
|
|
);
|
|
|
|
export const MainLayout = () => {
|
|
const [search, setSearch] = useState('');
|
|
const [quickAction, setQuickAction] = useState<QuickActionType>('none');
|
|
const [noteText, setNoteText] = useState('');
|
|
const [loginModalOpen, setLoginModalOpen] = useState(false);
|
|
const [operatorName, setOperatorName] = useState<string>('');
|
|
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
|
|
const activeSection: SectionKey = useMemo(() => {
|
|
const matched = Object.entries(routeToSection).find(([path]) => location.pathname.startsWith(path));
|
|
return (matched?.[1] || 'home') as SectionKey;
|
|
}, [location.pathname]);
|
|
|
|
const handleNavigate = (section: SectionKey) => {
|
|
navigate(sectionToRoute[section]);
|
|
};
|
|
|
|
const handleLoginSuccess = (phone: string) => {
|
|
// 实际项目中应该从后端获取用户信息
|
|
// 这里暂时使用手机号后4位作为操作员名称
|
|
const displayName = phone.slice(-4);
|
|
setOperatorName(displayName);
|
|
// 可以存储到 localStorage 或状态管理中
|
|
localStorage.setItem('operatorPhone', phone);
|
|
localStorage.setItem('operatorName', displayName);
|
|
};
|
|
|
|
// 初始化时检查是否有已登录的操作员
|
|
useEffect(() => {
|
|
const savedName = localStorage.getItem('operatorName');
|
|
if (savedName) {
|
|
setOperatorName(savedName);
|
|
}
|
|
}, []);
|
|
|
|
return (
|
|
<div className='h-screen bg-gray-50 text-gray-900 grid grid-cols-[240px_1fr] overflow-hidden'>
|
|
<Sidebar active={activeSection} onNavigate={handleNavigate} onQuickAction={setQuickAction} />
|
|
|
|
<div className='flex flex-col h-screen overflow-hidden'>
|
|
<TopBar
|
|
search={search}
|
|
onSearch={setSearch}
|
|
enableSearch={activeSection === 'exam'}
|
|
operatorName={operatorName}
|
|
onLoginClick={() => setLoginModalOpen(true)}
|
|
/>
|
|
<main className='p-6 flex-1 overflow-auto'>
|
|
<Outlet context={{ search, setSearch }} />
|
|
</main>
|
|
</div>
|
|
|
|
{loginModalOpen && (
|
|
<LoginModal
|
|
onClose={() => setLoginModalOpen(false)}
|
|
onLoginSuccess={handleLoginSuccess}
|
|
/>
|
|
)}
|
|
|
|
{quickAction !== 'none' && (
|
|
<QuickActionModal
|
|
action={quickAction}
|
|
noteText={noteText}
|
|
onNoteChange={setNoteText}
|
|
onClose={() => setQuickAction('none')}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
|