Add admin vision lab and LLM vision verification

这个提交包含在:
cryptocommuniums-afk
2026-03-15 00:41:09 +08:00
父节点 20e183d2da
当前提交 ad83ce9c68
修改 18 个文件,包含 915 行新增16 行删除

查看文件

@@ -23,14 +23,22 @@ import { useIsMobile } from "@/hooks/useMobile";
import {
LayoutDashboard, LogOut, PanelLeft, Target, Video,
Award, Activity, FileVideo, Trophy, Flame, Camera, CircleDot,
BookOpen, Bell
BookOpen, Bell, Microscope
} from "lucide-react";
import { CSSProperties, useEffect, useRef, useState } from "react";
import { useLocation, Redirect } from "wouter";
import { DashboardLayoutSkeleton } from './DashboardLayoutSkeleton';
import { TaskCenter } from "./TaskCenter";
const menuItems = [
type MenuItem = {
icon: typeof LayoutDashboard;
label: string;
path: string;
group: "main" | "analysis" | "stats" | "learn";
adminOnly?: boolean;
};
const menuItems: MenuItem[] = [
{ icon: LayoutDashboard, label: "仪表盘", path: "/dashboard", group: "main" },
{ icon: Target, label: "训练计划", path: "/training", group: "main" },
{ icon: Flame, label: "每日打卡", path: "/checkin", group: "main" },
@@ -43,6 +51,7 @@ const menuItems = [
{ icon: Trophy, label: "排行榜", path: "/leaderboard", group: "stats" },
{ icon: BookOpen, label: "教程库", path: "/tutorials", group: "learn" },
{ icon: Bell, label: "训练提醒", path: "/reminders", group: "learn" },
{ icon: Microscope, label: "视觉测试", path: "/vision-lab", group: "learn", adminOnly: true },
];
const mobileNavItems = [
@@ -111,7 +120,8 @@ function DashboardLayoutContent({
const isCollapsed = state === "collapsed";
const [isResizing, setIsResizing] = useState(false);
const sidebarRef = useRef<HTMLDivElement>(null);
const activeMenuItem = menuItems.find(item => item.path === location);
const visibleMenuItems = menuItems.filter(item => !item.adminOnly || user?.role === "admin");
const activeMenuItem = visibleMenuItems.find(item => item.path === location);
const isMobile = useIsMobile();
useEffect(() => {
@@ -180,7 +190,7 @@ function DashboardLayoutContent({
<SidebarContent className="gap-0">
<SidebarMenu className="px-2 py-1">
{/* Main group */}
{menuItems.filter(i => i.group === "main").map(item => {
{visibleMenuItems.filter(i => i.group === "main").map(item => {
const isActive = location === item.path;
return (
<SidebarMenuItem key={item.path}>
@@ -201,7 +211,7 @@ function DashboardLayoutContent({
{!isCollapsed && <div className="my-2 mx-2 border-t border-border/50" />}
{!isCollapsed && <p className="px-3 text-[10px] font-medium text-muted-foreground uppercase tracking-wider mb-1"></p>}
{menuItems.filter(i => i.group === "analysis").map(item => {
{visibleMenuItems.filter(i => i.group === "analysis").map(item => {
const isActive = location === item.path;
return (
<SidebarMenuItem key={item.path}>
@@ -222,7 +232,7 @@ function DashboardLayoutContent({
{!isCollapsed && <div className="my-2 mx-2 border-t border-border/50" />}
{!isCollapsed && <p className="px-3 text-[10px] font-medium text-muted-foreground uppercase tracking-wider mb-1"></p>}
{menuItems.filter(i => i.group === "stats").map(item => {
{visibleMenuItems.filter(i => i.group === "stats").map(item => {
const isActive = location === item.path;
return (
<SidebarMenuItem key={item.path}>
@@ -243,7 +253,7 @@ function DashboardLayoutContent({
{!isCollapsed && <div className="my-2 mx-2 border-t border-border/50" />}
{!isCollapsed && <p className="px-3 text-[10px] font-medium text-muted-foreground uppercase tracking-wider mb-1"></p>}
{menuItems.filter(i => i.group === "learn").map(item => {
{visibleMenuItems.filter(i => i.group === "learn").map(item => {
const isActive = location === item.path;
return (
<SidebarMenuItem key={item.path}>