"use client"; import { useQuery } from "@tanstack/react-query"; import clsx from "clsx"; import { Activity, Coins, FolderKanban, ImagePlus, LogOut, Sparkles, Ticket, UserRound, Users, } from "lucide-react"; import Link from "next/link"; import { usePathname, useRouter } from "next/navigation"; import { useEffect, useMemo } from "react"; import { api } from "@/lib/api"; import type { UserProfile } from "@/lib/types"; const navigation = [ { href: "/workspace/create", label: "工作台", description: "生成参数、提示词与素材联动", icon: Sparkles, }, { href: "/workspace/tasks", label: "任务记录", description: "查看队列、状态轮询与结果视频", icon: FolderKanban, }, { href: "/workspace/assets", label: "素材管理", description: "上传图片、视频和音频素材", icon: ImagePlus, }, { href: "/wallet", label: "钱包概览", description: "查看可用积分和冻结明细", icon: Coins, }, { href: "/wallet/recharge", label: "充值中心", description: "采购积分,补足生产额度", icon: Coins, }, { href: "/wallet/redeem", label: "兑换密钥", description: "使用兑换码快速充值", icon: Ticket, }, { href: "/invite", label: "邀请中心", description: "管理关系链与推广奖励", icon: Users, }, { href: "/profile", label: "个人资料", description: "维护账户信息与展示名", icon: UserRound, }, ]; function matchesPath(pathname: string, href: string) { return pathname === href || pathname.startsWith(`${href}/`); } export function SiteShell({ children }: { children: React.ReactNode }) { const pathname = usePathname(); const router = useRouter(); const { data, error, isLoading } = useQuery({ queryKey: ["web-me"], queryFn: () => api.get("/api/v1/auth/me"), }); useEffect(() => { if (error) { router.replace("/login"); } }, [error, router]); const title = useMemo(() => { const current = [...navigation] .sort((left, right) => right.href.length - left.href.length) .find((item) => matchesPath(pathname, item.href)); return current ?? navigation[0]; }, [pathname]); if (isLoading || !data) { return (
正在验证登录态并加载工作台...
); } return (
Creative Ops Console

{title.label}

{title.description}

会话正常
{data.publicId || "UNAVAILABLE"}
本地素材 / 本地存储 / mock 供应商
{children}
); }