Checkpoint: v4.0 media service, compose deploy, and verified docs

这个提交包含在:
cryptocommuniums-afk
2026-03-14 21:45:31 +08:00
父节点 27083d5af9
当前提交 d5431aee0e
修改 41 个文件,包含 4056 行新增883 行删除

查看文件

@@ -44,6 +44,14 @@ const menuItems = [
{ icon: Bell, label: "训练提醒", path: "/reminders", group: "learn" },
];
const mobileNavItems = [
{ icon: LayoutDashboard, label: "首页", path: "/dashboard" },
{ icon: Target, label: "计划", path: "/training" },
{ icon: CircleDot, label: "录制", path: "/recorder" },
{ icon: FileVideo, label: "视频", path: "/videos" },
{ icon: Activity, label: "进度", path: "/progress" },
];
const SIDEBAR_WIDTH_KEY = "sidebar-width";
const DEFAULT_WIDTH = 260;
const MIN_WIDTH = 200;
@@ -309,7 +317,31 @@ function DashboardLayoutContent({
</div>
</div>
)}
<main className="flex-1 p-4 md:p-6">{children}</main>
<main className={`flex-1 p-4 md:p-6 ${isMobile ? "pb-28" : ""}`}>{children}</main>
{isMobile && (
<nav className="mobile-safe-bottom fixed inset-x-0 bottom-0 z-50 border-t border-border/70 bg-background/95 px-2 pb-[calc(env(safe-area-inset-bottom,0px)+0.35rem)] pt-2 backdrop-blur supports-[backdrop-filter]:backdrop-blur">
<div className="mx-auto grid max-w-xl grid-cols-5 gap-1">
{mobileNavItems.map((item) => {
const isActive = location === item.path;
return (
<button
key={item.path}
type="button"
onClick={() => setLocation(item.path)}
className={`flex min-h-[52px] flex-col items-center justify-center rounded-2xl px-1 py-2 text-[11px] transition ${
isActive
? "bg-primary text-primary-foreground shadow-sm"
: "text-muted-foreground hover:bg-muted/70"
}`}
>
<item.icon className="mb-1 h-4 w-4" />
<span>{item.label}</span>
</button>
);
})}
</div>
</nav>
)}
</SidebarInset>
</>
);