"use client"; import Link from "next/link"; import { Bell, ChevronDown, Database, FileText, LayoutDashboard, ListChecks, LogOut, PanelLeftClose, PanelLeftOpen, PhoneCall, Settings, ShieldAlert, Sparkles, Users, X, FileSignature, } from "lucide-react"; import { useState, type ReactNode } from "react"; import { AssistantLauncher } from "@/components/admin/assistant-launcher"; import { clearToken, getRoleLabel } from "@/lib/auth"; import { canUseSection, isAdmin, isAdvisor, isStaff, visibleZones, type WorkspaceSection, } from "@/lib/roles"; import type { UserPayload } from "@/types/api"; import { Badge, cn } from "@/components/admin/ui"; export interface ShellNotification { id: string; title: string; body: string; time: string; tone: "alert" | "info" | "check"; section: WorkspaceSection; } /** 侧边栏条目元数据,与 roles.ts 的分区定义一一对应。 */ const NAV_META: Record< WorkspaceSection, { label: string; icon: typeof Users; requires: "staff" | "advisor" | "risk" | "admin" } > = { overview: { label: "工作台概览", icon: LayoutDashboard, requires: "staff" }, todos: { label: "我的待办", icon: ListChecks, requires: "advisor" }, customers: { label: "客户管理", icon: Users, requires: "advisor" }, drafts: { label: "投顾草稿", icon: FileSignature, requires: "advisor" }, visits: { label: "客户回访", icon: PhoneCall, requires: "advisor" }, risk: { label: "风险预警", icon: ShieldAlert, requires: "risk" }, workorders: { label: "工单处理", icon: FileText, requires: "risk" }, funds: { label: "基金数据", icon: Database, requires: "staff" }, nl2sql: { label: "智能问数", icon: Sparkles, requires: "staff" }, admin: { label: "系统管理", icon: Settings, requires: "admin" }, }; const REQUIREMENT_TEXT: Record = { staff: "仅员工账号可用", advisor: "需要投顾权限", risk: "需要风控权限", admin: "需要管理员权限", }; export function AdminShell({ user, section, onSectionChange, title, subtitle, notifications = [], children, }: { user: UserPayload; section: WorkspaceSection; onSectionChange: (section: WorkspaceSection) => void; title: string; subtitle: string; notifications?: ShellNotification[]; children: ReactNode; }) { const [collapsed, setCollapsed] = useState(false); const [showNotifications, setShowNotifications] = useState(false); const roleLabel = isAdmin(user) ? "管理员" : getRoleLabel(user.employee_role); const accessible = isStaff(user); return (

{title}

{subtitle}

{showNotifications && (
通知与提醒
{notifications.length === 0 ? (

暂无待处理提醒

) : ( <>
    {notifications.map((item) => (
  • ))}
点击提醒可跳转到对应功能区
)}
)}
{(user.real_name ?? user.username ?? "员").slice(0, 1)}

{user.real_name ?? user.username}

{roleLabel}

{!accessible && (
当前账号不是员工账号,部分功能不可用
)} {children}
{/* 投顾助手常驻入口:右下角悬浮球,打开后是抽屉式会话面板 */} {accessible && isAdvisor(user) && }
); }