RMO-Front/src/components/DashboardLayout.tsx

268 lines
10 KiB
TypeScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ReactNode, useState } from 'react'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import { useAuth } from '../contexts/AuthContext'
import './DashboardLayout.css'
interface DashboardLayoutProps {
children: ReactNode
}
function DashboardLayout({ children }: DashboardLayoutProps) {
const { user, logout } = useAuth()
const location = useLocation()
const navigate = useNavigate()
const [sidebarOpen, setSidebarOpen] = useState(true)
const [rmoMenuOpen, setRmoMenuOpen] = useState(false)
const [responsibilityMenuOpen, setResponsibilityMenuOpen] = useState(false)
const [systemMenuOpen, setSystemMenuOpen] = useState(false)
const isActive = (path: string) => location.pathname === path
const isActiveParent = (path: string) => location.pathname.startsWith(path)
const isActiveParentMulti = (paths: string[]) => paths.some(path => location.pathname.startsWith(path))
// 根据角色判断权限
const isPolicyHolder = user?.role === '投保人'
const isInsurer = user?.role === '保险人'
// 投保人可见:项目列表、理赔进度、智能工具
// 保险人可见:询价列表、理赔进度
const handleLogout = () => {
logout()
navigate('/login')
}
return (
<div className="dashboard-layout">
{/* 侧边栏 */}
<aside className={`dashboard-sidebar ${sidebarOpen ? 'open' : 'closed'}`}>
<div className="sidebar-header">
<Link to="/dashboard" className="sidebar-logo">
<h2>RMO</h2>
<span></span>
</Link>
<button
className="sidebar-toggle"
onClick={() => setSidebarOpen(!sidebarOpen)}
aria-label="切换侧边栏"
>
{sidebarOpen ? '◀' : '▶'}
</button>
</div>
<nav className="sidebar-nav">
<Link
to="/dashboard"
className={`nav-item ${isActive('/dashboard') && !isActiveParentMulti(['/dashboard/projects', '/dashboard/project-quotes', '/dashboard/inquiries', '/dashboard/claims', '/dashboard/tools']) ? 'active' : ''}`}
>
<span className="nav-icon">📊</span>
{sidebarOpen && <span className="nav-text"></span>}
</Link>
{/* 投保人可见:项目报价、项目列表 */}
{isPolicyHolder && (
<>
<Link
to="/dashboard/project-quotes"
className={`nav-item ${isActiveParent('/dashboard/project-quotes') ? 'active' : ''}`}
>
<span className="nav-icon">💰</span>
{sidebarOpen && <span className="nav-text"></span>}
</Link>
<Link
to="/dashboard/projects"
className={`nav-item ${isActiveParent('/dashboard/projects') ? 'active' : ''}`}
>
<span className="nav-icon">📋</span>
{sidebarOpen && <span className="nav-text"></span>}
</Link>
</>
)}
{/* 保险人可见:询价列表 */}
{isInsurer && (
<Link
to="/dashboard/inquiries"
className={`nav-item ${isActiveParent('/dashboard/inquiries') ? 'active' : ''}`}
>
<span className="nav-icon">💼</span>
{sidebarOpen && <span className="nav-text"></span>}
</Link>
)}
{/* 投保人、保险人可见:理赔进度 */}
{(isPolicyHolder || isInsurer) && (
<Link
to="/dashboard/claims"
className={`nav-item ${isActiveParent('/dashboard/claims') ? 'active' : ''}`}
>
<span className="nav-icon">📝</span>
{sidebarOpen && <span className="nav-text"></span>}
</Link>
)}
{/* 智能工具:所有登录用户可见 */}
<div className="nav-group">
<div className={`nav-item ${isActiveParentMulti(['/dashboard/tools']) ? 'active' : ''}`}>
<span className="nav-icon">🛠</span>
{sidebarOpen && <span className="nav-text"></span>}
</div>
{isActiveParentMulti(['/dashboard/tools']) && (
<div className="nav-submenu">
{/* 保费测算工具:所有登录用户可见 */}
<Link
to="/dashboard/tools/premium-calculator"
className={`nav-subitem ${isActive('/dashboard/tools/premium-calculator') ? 'active' : ''}`}
>
</Link>
{/* ICF智能修改仅投保人可见 */}
{isPolicyHolder && (
<Link
to="/dashboard/tools/icf-editor"
className={`nav-subitem ${isActive('/dashboard/tools/icf-editor') ? 'active' : ''}`}
>
ICF智能修改
</Link>
)}
{/* 方案风险评分:仅投保人可见 */}
{isPolicyHolder && (
<Link
to="/dashboard/tools/risk-scoring"
className={`nav-subitem ${isActive('/dashboard/tools/risk-scoring') ? 'active' : ''}`}
>
</Link>
)}
{/* 方案风险评估:所有登录用户可见 */}
<Link
to="/dashboard/tools/protocol-risk"
className={`nav-subitem ${isActive('/dashboard/tools/protocol-risk') ? 'active' : ''}`}
>
</Link>
{/* 药安查:所有登录用户可见 */}
<Link
to="/dashboard/tools/drug-safety"
className={`nav-subitem ${isActive('/dashboard/tools/drug-safety') ? 'active' : ''}`}
>
</Link>
</div>
)}
</div>
</nav>
</aside>
{/* 主内容区 */}
<div className="dashboard-main">
{/* 顶部栏 */}
<header className="dashboard-header">
<div className="header-left">
<Link to="/" className="header-logo">
<h2>RMO</h2>
<span></span>
</Link>
<nav className="header-nav">
<Link to="/" className={isActive('/') ? 'active' : ''}>
</Link>
{/* 风险职责 */}
<div
className="nav-dropdown"
onMouseEnter={() => setResponsibilityMenuOpen(true)}
onMouseLeave={() => setResponsibilityMenuOpen(false)}
>
<Link
to="/RMO-About-Responsibility"
className={isActiveParentMulti(['/RMO-About-Responsibility', '/sponsor', '/Holder', '/institution', '/service-provider', '/participant']) ? 'active' : ''}
>
</Link>
{responsibilityMenuOpen && (
<div className="dropdown-menu">
<Link to="/sponsor"></Link>
<Link to="/Holder"></Link>
<Link to="/participant"></Link>
<Link to="/institution"></Link>
<Link to="/service-provider">CXO职责</Link>
</div>
)}
</div>
{/* 临床试验 */}
<div
className="nav-dropdown"
onMouseEnter={() => setRmoMenuOpen(true)}
onMouseLeave={() => setRmoMenuOpen(false)}
>
<Link
to="/rmo-mode"
className={isActiveParentMulti(['/rmo-mode', '/insurance', '/guarantee', '/insurance-guarantee']) ? 'active' : ''}
>
</Link>
{rmoMenuOpen && (
<div className="dropdown-menu">
<Link to="/rmo-mode/insurance"></Link>
<Link to="/rmo-mode/guarantee"></Link>
<Link to="/rmo-mode/insurance-guarantee"></Link>
</div>
)}
</div>
{/* 上市应用 */}
<Link to="/post-market" className={isActive('/post-market') ? 'active' : ''}>
</Link>
{/* 海外风险 */}
<Link to="/overseas" className={isActive('/overseas') ? 'active' : ''}>
</Link>
{/* 资源中心 */}
<div
className="nav-dropdown"
onMouseEnter={() => setSystemMenuOpen(true)}
onMouseLeave={() => setSystemMenuOpen(false)}
>
<Link
to="/system-management"
className={isActiveParentMulti(['/system-management', '/faq']) ? 'active' : ''}
>
</Link>
{systemMenuOpen && (
<div className="dropdown-menu">
<Link to="/system-management/laws"></Link>
<Link to="/system-management/practice-guide"></Link>
<Link to="/system-management/training"></Link>
<Link to="/system-management/faq"></Link>
</div>
)}
</div>
</nav>
</div>
<div className="header-right">
<div className="user-info">
<span className="user-name">{user?.name}</span>
<span className="user-role">{user?.role}</span>
</div>
<button onClick={handleLogout} className="logout-btn">
退
</button>
</div>
</header>
{/* 页面内容 */}
<main className="dashboard-content">
{children}
</main>
</div>
</div>
)
}
export default DashboardLayout