生产管理系统前端 - 1.修改了左侧菜单的icon 2. 顶部菜单的绿色显示 test版本

This commit is contained in:
2025-10-24 14:34:32 +08:00
parent e784e68404
commit 7615ca9895
6 changed files with 216 additions and 214 deletions

View File

@@ -61,6 +61,7 @@
"zustand": "^5.0.8"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@tailwindcss/vite": "^4.1.14",
"@types/node": "^20.10.0",
"@types/react": "^18.3.11",
@@ -88,6 +89,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -115,6 +117,7 @@
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/@emnapi/core/-/core-1.6.0.tgz",
"integrity": "sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -136,6 +139,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
"integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -1307,6 +1311,7 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
"dev": true,
"license": "ISC",
"dependencies": {
"minipass": "^7.0.4"
@@ -1319,6 +1324,7 @@
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -1329,6 +1335,7 @@
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
@@ -1339,6 +1346,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -1361,12 +1369,14 @@
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@@ -1377,6 +1387,7 @@
"version": "0.2.12",
"resolved": "https://registry.npmmirror.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
"integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -3485,6 +3496,7 @@
"version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.14.tgz",
"integrity": "sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.4",
@@ -3500,6 +3512,7 @@
"version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.14.tgz",
"integrity": "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@@ -3531,6 +3544,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3547,6 +3561,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3563,6 +3578,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3579,6 +3595,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3595,6 +3612,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3611,6 +3629,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3627,6 +3646,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3643,6 +3663,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3659,6 +3680,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3683,6 +3705,7 @@
"cpu": [
"wasm32"
],
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -3704,6 +3727,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3720,6 +3744,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3733,6 +3758,7 @@
"version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.14.tgz",
"integrity": "sha512-BdMjIxy7HUNThK87C7BC8I1rE8BVUsfNQSI5siQ4JK3iIa3w0XyVvVL9SXLWO//CtYTcp1v7zci0fYwJOjB+Zg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
@@ -3761,6 +3787,7 @@
"version": "0.10.1",
"resolved": "https://registry.npmmirror.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -4980,6 +5007,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
@@ -5498,6 +5526,7 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
"devOptional": true,
"license": "Apache-2.0",
"engines": {
"node": ">=8"
@@ -5598,6 +5627,7 @@
"version": "5.18.3",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
"dev": true,
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
@@ -6900,6 +6930,7 @@
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true,
"license": "ISC"
},
"node_modules/graphemer": {
@@ -7571,6 +7602,7 @@
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
"dev": true,
"license": "MIT",
"bin": {
"jiti": "lib/jiti-cli.mjs"
@@ -7693,6 +7725,7 @@
"version": "1.30.1",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
"dev": true,
"license": "MPL-2.0",
"dependencies": {
"detect-libc": "^2.0.3"
@@ -7724,6 +7757,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7744,6 +7778,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7764,6 +7799,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7784,6 +7820,7 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7804,6 +7841,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7824,6 +7862,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7844,6 +7883,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7864,6 +7904,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7884,6 +7925,7 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7904,6 +7946,7 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -8109,6 +8152,7 @@
"version": "0.30.19",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
@@ -8231,6 +8275,7 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"dev": true,
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
@@ -8240,6 +8285,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
"integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
"dev": true,
"license": "MIT",
"dependencies": {
"minipass": "^7.1.2"
@@ -11359,6 +11405,7 @@
"version": "8.5.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"dev": true,
"funding": [
{
"type": "opencollective",
@@ -12566,6 +12613,7 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -12579,6 +12627,7 @@
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.1.tgz",
"integrity": "sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==",
"dev": true,
"license": "ISC",
"dependencies": {
"@isaacs/fs-minipass": "^4.0.0",
@@ -13282,6 +13331,7 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"

View File

@@ -2,137 +2,6 @@
import { ReactNode } from 'react'
// import {SideBarOld} from '@/components/layouts/SideBar/SideBarOld'
// 中心配置路由数据
const centralConfigData = {
navMain: [
{
title: "租户管理",
url: "/central-config/tenant",
icon: "🏢",
items: [
{
title: "企业审核",
url: "/central-config/tenant/enterprise-audit",
isActive: false
},
{
title: "审核历史",
url: "/central-config/tenant/audit-history",
isActive: false
},
{
title: "企业信息",
url: "/central-config/tenant/enterprise-info",
isActive: false
},
{
title: "用户管理",
url: "/central-config/tenant/user-management",
isActive: false
}
]
},
{
title: "用户管理",
url: "/central-config/user",
icon: "👥",
items: [
{
title: "员工管理",
url: "/central-config/user/employee",
isActive: false
},
{
title: "角色管理",
url: "/central-config/user/role",
isActive: false
},
{
title: "菜单管理",
url: "/central-config/user/menu",
isActive: false
},
{
title: "权限配置管理",
url: "/central-config/user/permission",
isActive: false
}
]
},
{
title: "系统参数",
url: "/central-config/system",
icon: "🔧",
items: [
{
title: "系统设置",
url: "/central-config/system/settings",
isActive: false
},
{
title: "分类字典",
url: "/central-config/system/category",
isActive: false
},
{
title: "数据字典",
url: "/central-config/system/dictionary",
isActive: false
}
]
},
{
title: "系统监控",
url: "/central-config/monitor",
icon: "📈",
items: [
{
title: "登录日志",
url: "/central-config/monitor/login-log",
isActive: false
},
{
title: "操作日志",
url: "/central-config/monitor/operation-log",
isActive: false
},
{
title: "性能监控",
url: "/central-config/monitor/performance",
isActive: false
},
{
title: "网络日志",
url: "/central-config/monitor/network-log",
isActive: false
}
]
},
{
title: "消息中心",
url: "/central-config/message",
icon: "📨",
items: [
{
title: "消息发送",
url: "/central-config/message/send",
isActive: false
},
{
title: "消息模版",
url: "/central-config/message/template",
isActive: false
},
{
title: "消息日志",
url: "/central-config/message/log",
isActive: false
}
]
}
]
}
export default function CentralConfigLayout({
children,
}: {

View File

@@ -2,13 +2,14 @@ import {Navbar1} from "@/components/layouts/Navbar"
import {SideBarOld} from '@/components/layouts/SideBar/SideBarOld'
import '@/styles/globals.css'
import { ThemeProvider } from 'next-themes'
import { Building2, Users, Cog, Activity, Mail } from 'lucide-react'
const centralConfigData = {
navMain: [
{
title: "租户管理",
url: "/central-config/tenant",
icon: "🏢",
icon: <Building2 className="w-4 h-4" />,
items: [
{
title: "企业审核",
@@ -35,7 +36,7 @@ const centralConfigData = {
{
title: "用户管理",
url: "/central-config/user",
icon: "👥",
icon: <Users className="w-4 h-4" />,
items: [
{
title: "员工管理",
@@ -62,7 +63,7 @@ const centralConfigData = {
{
title: "系统参数",
url: "/central-config/system",
icon: "🔧",
icon: <Cog className="w-4 h-4" />,
items: [
{
title: "系统设置",
@@ -84,7 +85,7 @@ const centralConfigData = {
{
title: "系统监控",
url: "/central-config/monitor",
icon: "📈",
icon: <Activity className="w-4 h-4" />,
items: [
{
title: "登录日志",
@@ -111,7 +112,7 @@ const centralConfigData = {
{
title: "消息中心",
url: "/central-config/message",
icon: "📨",
icon: <Mail className="w-4 h-4" />,
items: [
{
title: "消息发送",

View File

@@ -8,12 +8,15 @@ import { ThemeToggle } from './ThemeToggle';
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 { usePathname } from 'next/navigation';
import { useRef, useEffect, useState } from 'react';
// 注释掉 Accordion 相关导入,因为不再需要二级菜单
// import {
// Accordion,
// AccordionContent,
// AccordionItem,
// AccordionTrigger,
// } from "@/components/ui/accordion";
import { useLayoutStore } from '@/stores/useLayoutStore';
import { Button } from "@/components/ui/button";
import {
@@ -119,10 +122,20 @@ const Navbar1 = () => {
const logo = navbarData.logo
const menu = navbarData.menu
const auth = navbarData.auth
const pathname = usePathname()
const containerStyle = {
maxWidth:"100%",marginLeft:"0px",marginRight:"0px",paddingLeft:"1rem",paddingRight:"0rem"
}
// 检查当前路径是否匹配菜单项
const isMenuActive = (url: string) => {
// 精确匹配
if (pathname === url) return true;
// 检查是否是该菜单下的子路径
if (pathname.startsWith(url + '/')) return true;
return false;
}
// 使用自定义 Hook 计算高度
const { elementRef, updateHeight } = useElementHeight({
immediate: true, // 立即计算高度
@@ -133,6 +146,7 @@ const Navbar1 = () => {
}
});
// 监听页面高度变化
useViewHeight();
@@ -191,8 +205,7 @@ const Navbar1 = () => {
`}</style>
<NavigationMenu>
<NavigationMenuList className="flex gap-1 min-w-max">
{menu.map((item) => renderMenuItem(item))}
{menu.map((item) => renderMenuItem(item, isMenuActive))}
</NavigationMenuList>
</NavigationMenu>
</div>
@@ -234,13 +247,10 @@ const Navbar1 = () => {
</SheetTitle>
</SheetHeader>
<div className="flex flex-col gap-6 p-4">
<Accordion
type="single"
collapsible
className="flex w-full flex-col gap-4"
>
{menu.map((item) => renderMobileMenuItem(item))}
</Accordion>
{/* 简化移动端菜单,不再使用 Accordion */}
<div className="flex w-full flex-col gap-4">
{menu.map((item) => renderMobileMenuItem(item, isMenuActive))}
</div>
<div className="flex flex-col gap-3">
<div className="flex justify-center">
@@ -264,78 +274,129 @@ const Navbar1 = () => {
);
};
const renderMenuItem = (item: MenuItem) => {
if (item.items) {
return (
<NavigationMenuItem key={item.title}>
<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>
))}
</NavigationMenuContent>
</NavigationMenuItem>
);
}
const renderMenuItem = (item: MenuItem, isMenuActive: (url: string) => boolean) => {
// 注释掉二级菜单相关代码,项目不需要二级菜单
// if (item.items) {
// return (
// <NavigationMenuItem key={item.title}>
// <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>
// ))}
// </NavigationMenuContent>
// </NavigationMenuItem>
// );
// }
return (
<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 rounded-md px-4 py-2 text-sm font-medium transition-colors gap-2 whitespace-nowrap"
data-menu-item="true"
data-menu-url={item.url}
className={`
inline-flex h-10 w-max items-center justify-center rounded-md px-4 py-2 text-sm font-medium gap-2 whitespace-nowrap relative
${isMenuActive(item.url)
? 'bg-primary/10'
: 'bg-background hover:bg-muted hover:text-accent-foreground'
}
[&:not([data-active])]:text-foreground
`}
>
{item.icon && <span className="shrink-0">{item.icon}</span>}
{item.title}
{item.icon && (
<span className={`
shrink-0
${isMenuActive(item.url)
? 'text-primary'
: 'text-muted-foreground'
}
hover:text-primary
[&.group-data-[state=open]]:text-muted-foreground
`}>
{item.icon}
</span>
)}
<div className="relative">
<span className={isMenuActive(item.url) ? 'text-primary' : ''}>
{item.title}
</span>
{/* 激活菜单项下方的横条 */}
{isMenuActive(item.url) && (
<div className="absolute -bottom-1 left-0 right-0 h-[0.5px] bg-primary"></div>
)}
</div>
</NavigationMenuLink>
</NavigationMenuItem>
);
};
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 gap-2">
{item.icon && <span className="shrink-0">{item.icon}</span>}
{item.title}
</AccordionTrigger>
<AccordionContent className="mt-2">
{item.items.map((subItem) => (
<SubMenuLink key={subItem.title} item={subItem} />
))}
</AccordionContent>
</AccordionItem>
);
}
const renderMobileMenuItem = (item: MenuItem, isMenuActive: (url: string) => boolean) => {
// 注释掉移动端二级菜单相关代码
// 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 gap-2">
// {item.icon && <span className="shrink-0">{item.icon}</span>}
// {item.title}
// </AccordionTrigger>
// <AccordionContent className="mt-2">
// {item.items.map((subItem) => (
// <SubMenuLink key={subItem.title} item={subItem} />
// ))}
// </AccordionContent>
// </AccordionItem>
// );
// }
return (
<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>
);
};
const SubMenuLink = ({ item }: { item: MenuItem }) => {
return (
<a
className="hover:bg-muted hover:text-accent-foreground flex min-w-80 select-none flex-row gap-4 rounded-md p-3 leading-none no-underline outline-none transition-colors"
key={item.title}
href={item.url}
className={`
text-md font-semibold flex items-center gap-2 p-2 rounded-md transition-colors
${isMenuActive(item.url)
? 'bg-primary/10 text-primary'
: 'hover:bg-muted hover:text-accent-foreground'
}
`}
>
<div className="text-foreground">{item.icon}</div>
<div>
<div className="text-sm font-semibold">{item.title}</div>
{item.description && (
<p className="text-muted-foreground text-sm leading-snug">
{item.description}
</p>
)}
</div>
{item.icon && (
<span className={`
shrink-0
${isMenuActive(item.url) ? 'text-primary' : 'text-muted-foreground'}
`}>
{item.icon}
</span>
)}
<span className={isMenuActive(item.url) ? 'text-primary' : ''}>
{item.title}
</span>
</a>
);
};
// 注释掉 SubMenuLink 组件,因为不再需要二级菜单
// const SubMenuLink = ({ item }: { item: MenuItem }) => {
// return (
// <a
// className="hover:bg-muted hover:text-accent-foreground flex min-w-80 select-none flex-row gap-4 rounded-md p-3 leading-none no-underline outline-none transition-colors"
// href={item.url}
// >
// <div className="text-foreground">{item.icon}</div>
// <div>
// <div className="text-sm font-semibold">{item.title}</div>
// {item.description && (
// <p className="text-muted-foreground text-sm leading-snug">
// {item.description}
// </p>
// )}
// </div>
// </a>
// );
// };
export { Navbar1 };

View File

@@ -180,7 +180,7 @@ export function SideBarOld({
const menus = sidebarData.navMain.map(item => ({
id: item.url.replace(/\/[^\/]+/g, '').replace('/', '') || item.title.replace(/\s+/g, '-').toLowerCase(),
label: item.title,
icon: <span className="text-lg">{item.icon}</span>,
icon: item.icon,
children: item.items?.map(child => ({
id: child.url.split('/').pop() || child.title.replace(/\s+/g, '-').toLowerCase(),
label: child.title,

View File

@@ -44,6 +44,19 @@ export function LeftSidebar({
return new Set<string>();
};
// 检查菜单是否有子菜单被选中或是否应该高亮
const isMenuActive = (menu: MenuItem) => {
// 检查是否有子菜单被选中
if (menu.children?.some(child => child.path === activePath)) {
return true;
}
// 如果当前路径匹配菜单的URL无子菜单的情况
if (activePath && activePath.includes(menu.id)) {
return true;
}
return false;
};
const [expandedMenus, setExpandedMenus] = useState<Set<string>>(getInitialExpandedMenus());
// 不自动展开菜单,由用户手动控制
@@ -121,14 +134,18 @@ export function LeftSidebar({
<Button
variant="ghost"
className={cn(
"w-full justify-between text-sm font-normal",
isCollapsed ? "justify-center px-2 py-3" : "px-3 py-2"
"w-full justify-between text-sm font-normal group",
isCollapsed ? "justify-center px-2 py-3" : "px-3 py-2",
isMenuActive(menu) && "text-primary"
)}
title={isCollapsed ? menu.label : undefined}
>
<div className="flex items-center gap-2">
{menu.icon && (
<span className="flex-shrink-0">
<span className={cn(
"flex-shrink-0",
isMenuActive(menu) ? "text-primary" : "text-muted-foreground group-hover:text-primary"
)}>
{menu.icon}
</span>
)}
@@ -159,8 +176,8 @@ export function LeftSidebar({
className={cn(
"w-full justify-start text-xs font-normal h-8",
activePath === child.path
? "bg-green-50 text-green-700 font-medium hover:bg-green-50"
: "hover:bg-gray-100 hover:text-gray-900"
? "bg-primary/10 text-primary font-medium hover:bg-primary/10"
: "hover:bg-accent hover:text-foreground"
)}
onClick={() => child.path && onNavigate(child.path)}
>
@@ -175,14 +192,18 @@ export function LeftSidebar({
<Button
variant="ghost"
className={cn(
"w-full justify-start text-sm font-normal",
isCollapsed ? "justify-center px-2 py-3" : "px-3 py-2"
"w-full justify-start text-sm font-normal group",
isCollapsed ? "justify-center px-2 py-3" : "px-3 py-2",
isMenuActive(menu) && "text-primary"
)}
title={isCollapsed ? menu.label : undefined}
>
<div className="flex items-center gap-2">
{menu.icon && (
<span className="flex-shrink-0">
<span className={cn(
"flex-shrink-0",
isMenuActive(menu) ? "text-primary" : "text-muted-foreground group-hover:text-primary"
)}>
{menu.icon}
</span>
)}