生产管理系统前端 1.修复系统导航过长的问题 2.利用旧菜单交互 开发菜单与导航

This commit is contained in:
2025-10-22 15:18:36 +08:00
parent 9afc680833
commit 7a21043dd8
25 changed files with 1843 additions and 109 deletions

View File

@@ -1,12 +1,20 @@
import { Menu } from "lucide-react";
'use client';
import { Book, Menu, Sunset, Trees, Zap } from "lucide-react";
import { Tractor, Map, Clipboard, Package, Brain, Droplets, Settings } from 'lucide-react';
import { MessageBell } from './components/MessageBell';
import { UserProfile } from './components/UserProfile';
import { AuthProvider } from './components/auth/AuthContext';
import { useElementHeight } from '@/hooks/useElementHeight';
import { useViewHeight } from '@/hooks/useViewHeight';
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { Button } from "@/components/ui/button";
import { useLayoutStore } from '@/stores/useLayoutStore';
import { Button } from "@/components/ui/button";
import {
NavigationMenu,
NavigationMenuContent,
@@ -23,8 +31,7 @@ import {
SheetTrigger,
} from "@/components/ui/sheet";
// 菜单项接口定义
export interface MenuItem {
interface MenuItem {
title: string;
url: string;
description?: string;
@@ -32,45 +39,31 @@ export interface MenuItem {
items?: MenuItem[];
}
// Logo接口定义
export interface LogoConfig {
url: string;
src: string;
alt: string;
title: string;
}
// 认证接口定义
export interface AuthConfig {
login: {
title: string;
interface Navbar1Props {
logo?: {
url: string;
};
signup: {
src: string;
alt: string;
title: string;
url: string;
};
}
// Navbar数据接口定义
export interface NavbarData {
logo?: LogoConfig;
menu?: MenuItem[];
auth?: AuthConfig;
auth?: {
login: {
title: string;
url: string;
};
signup: {
title: string;
url: string;
};
};
}
// Navbar组件Props接口定义
export interface NavbarProps {
navbar?: NavbarData;
}
// 默认Navbar数据
const defaultNavbar: NavbarData = {
const navbarData = {
logo: {
url: "/",
src: "https://deifkwefumgah.cloudfront.net/shadcnblocks/block/logos/shadcnblockscom-icon.svg",
alt: "Crop-X Logo",
title: "Crop-X 智慧农业",
title: "智慧农业生产管理系统",
},
menu: [
{
@@ -121,22 +114,47 @@ const defaultNavbar: NavbarData = {
signup: { title: "注册", url: "/register" },
},
};
const Navbar1 = () => {
const logo = navbarData.logo
const menu = navbarData.menu
const auth = navbarData.auth
const containerStyle = {
maxWidth:"100%",marginLeft:"0px",marginRight:"0px",paddingLeft:"1rem",paddingRight:"0rem"
}
// 新的Navbar组件支持外部传入navbar参数
export function Navbar({ navbar }: NavbarProps) {
// 使用外部传入的navbar数据如果没有则使用默认数据
const navbarData = navbar || defaultNavbar;
const logo = navbarData.logo || defaultNavbar.logo;
const menu = navbarData.menu || defaultNavbar.menu;
const auth = navbarData.auth || defaultNavbar.auth;
// 使用自定义 Hook 计算高度
const { elementRef, updateHeight } = useElementHeight({
immediate: true, // 立即计算高度
onUpdate: (height: number) => {
// 更新 Zustand store 中的状态
const { setNavigatorHeight } = useLayoutStore.getState();
setNavigatorHeight(height);
}
});
// 监听页面高度变化
useViewHeight();
const handleMessageClick = () => {
// 处理消息点击事件,可以跳转到消息中心页面
console.log('Navigate to message center');
};
const handleProfileClick = () => {
// 处理个人中心点击事件
console.log('Navigate to profile page');
};
return (
<section className="py-4">
<div className="container">
<AuthProvider>
<section className="py-4" ref={elementRef}>
<div className="container" style = {containerStyle}>
{/* Desktop Menu */}
<nav className="hidden justify-between lg:flex">
<div className="flex items-center gap-6">
{/* Logo */}
<span className="flex items-center gap-2">
<div className="flex items-center gap-3 flex-shrink-0">
<div className="w-10 h-10 bg-green-600 rounded-lg flex items-center justify-center">
<Tractor className="w-6 h-6 text-white" />
@@ -146,21 +164,41 @@ export function Navbar({ navbar }: NavbarProps) {
<p className="text-xs text-muted-foreground">Smart Agriculture Management System</p>
</div>
</div>
<div className="flex items-center">
</span>
<div className="flex items-center gap-1 overflow-x-auto flex-1 min-w-0" style={{ maxWidth: '70vw' }}>
<style jsx>{`
div::-webkit-scrollbar {
height: 6px;
}
div::-webkit-scrollbar-track {
background: transparent;
}
div::-webkit-scrollbar-thumb {
background-color: #d1d5db;
border-radius: 3px;
}
div::-webkit-scrollbar-thumb:hover {
background-color: #9ca3af;
}
div {
scrollbar-width: thin;
scrollbar-color: #d1d5db transparent;
}
.navigation-menu-container {
max-width: 70vw;
}
`}</style>
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuList className="flex gap-1 min-w-max">
{menu.map((item) => renderMenuItem(item))}
</NavigationMenuList>
</NavigationMenu>
</div>
</div>
<div className="flex gap-2">
<Button asChild variant="outline" size="sm">
<a href={auth.login.url}>{auth.login.title}</a>
</Button>
<Button asChild size="sm">
<a href={auth.signup.url}>{auth.signup.title}</a>
</Button>
<div className="flex gap-2" style = {{alignItems:"center"}}>
<MessageBell onMessageClick={handleMessageClick} />
<UserProfile onProfileClick={handleProfileClick} />
</div>
</nav>
@@ -203,15 +241,12 @@ export function Navbar({ navbar }: NavbarProps) {
</Accordion>
<div className="flex flex-col gap-3">
<Button asChild variant="outline">
<a href={auth.login.url}>{auth.login.title}</a>
</Button>
<Button asChild>
<a href={auth.signup.url}>{auth.signup.title}</a>
</Button>
<Button asChild>
</Button>
<div className="flex justify-center">
<MessageBell onMessageClick={handleMessageClick} />
</div>
<div className="flex justify-center">
<UserProfile onProfileClick={handleProfileClick} />
</div>
</div>
</div>
</SheetContent>
@@ -220,16 +255,18 @@ export function Navbar({ navbar }: NavbarProps) {
</div>
</div>
</section>
</AuthProvider>
);
}
};
const renderMenuItem = (item: MenuItem) => {
if (item.items) {
return (
<NavigationMenuItem key={item.title}>
<NavigationMenuTrigger>{item.title}</NavigationMenuTrigger>
<NavigationMenuTrigger className="whitespace-nowrap">{item.title}</NavigationMenuTrigger>
<NavigationMenuContent className="bg-popover text-popover-foreground">
{item.items.map((subItem) => (
<NavigationMenuLink asChild key={subItem.title} className="w-80">
<SubMenuLink item={subItem} />
</NavigationMenuLink>
@@ -243,9 +280,9 @@ const renderMenuItem = (item: MenuItem) => {
<NavigationMenuItem key={item.title}>
<NavigationMenuLink
href={item.url}
className="bg-background hover:bg-muted hover:text-accent-foreground group inline-flex h-10 w-max items-center justify-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors"
className="bg-background hover:bg-muted hover:text-accent-foreground group inline-flex h-10 w-max items-center justify-center rounded-md px-4 py-2 text-sm font-medium transition-colors gap-2 whitespace-nowrap"
>
{item.icon}
{item.icon && <span className="shrink-0">{item.icon}</span>}
{item.title}
</NavigationMenuLink>
</NavigationMenuItem>
@@ -256,7 +293,8 @@ const renderMobileMenuItem = (item: MenuItem) => {
if (item.items) {
return (
<AccordionItem key={item.title} value={item.title} className="border-b-0">
<AccordionTrigger className="text-md py-0 font-semibold hover:no-underline">
<AccordionTrigger className="text-md py-0 font-semibold hover:no-underline gap-2">
{item.icon && <span className="shrink-0">{item.icon}</span>}
{item.title}
</AccordionTrigger>
<AccordionContent className="mt-2">
@@ -269,7 +307,8 @@ const renderMobileMenuItem = (item: MenuItem) => {
}
return (
<a key={item.title} href={item.url} className="text-md font-semibold">
<a key={item.title} href={item.url} className="text-md font-semibold flex items-center gap-2">
{item.icon && <span className="shrink-0">{item.icon}</span>}
{item.title}
</a>
);
@@ -293,3 +332,5 @@ const SubMenuLink = ({ item }: { item: MenuItem }) => {
</a>
);
};
export { Navbar1 };