278 lines
8.6 KiB
JavaScript
Executable File
278 lines
8.6 KiB
JavaScript
Executable File
import React, { useState, useRef, useEffect } from 'react';
|
||
import { useNavigate, Link } from 'react-router-dom';
|
||
import { useAuth } from '../context/AuthContext';
|
||
import './Navbar.css';
|
||
|
||
const productMenu = [
|
||
{
|
||
key: 'smart',
|
||
label: '智能系列',
|
||
subs: [
|
||
{
|
||
key: 'N96',
|
||
label: 'N96',
|
||
products: [
|
||
{ name: 'N96', desc: 'Android11,高性能,适配复杂场景', image: '/uploads/menu/menu_n96.png' }
|
||
]
|
||
},
|
||
{
|
||
key: 'N96P',
|
||
label: 'N96P',
|
||
products: [
|
||
{ name: 'N96P', desc: 'Android14,高性能,适配复杂场景', image: '/uploads/menu/menu_n96p.png' }
|
||
]
|
||
},
|
||
{
|
||
key: 'N92',
|
||
label: 'N92',
|
||
products: [
|
||
{ name: 'N92', desc: 'Android13,高性能,适配复杂场景', image: '/uploads/menu/menu_n92.png' }
|
||
]
|
||
},
|
||
{
|
||
key: 'N86P',
|
||
label: 'N86P',
|
||
products: [
|
||
{ name: 'N86P', desc: 'Android13,高性能,适配复杂场景', image: '/uploads/menu/menu_n86p.png' }
|
||
]
|
||
},
|
||
{
|
||
key: 'N86',
|
||
label: 'N86',
|
||
products: [
|
||
{ name: 'N86', desc: 'Android9,高性能,适配复杂场景', image: '/uploads/menu/menu_n86.png' }
|
||
]
|
||
},
|
||
{
|
||
key: 'N82',
|
||
label: 'N82',
|
||
products: [
|
||
{ name: 'N82', desc: 'Android10,高性能,适配复杂场景', image: '/uploads/menu/menu_n82.png' }
|
||
]
|
||
},
|
||
{
|
||
key: 'N80',
|
||
label: 'N80',
|
||
products: [
|
||
{ name: 'N80', desc: 'Android13,高性能,适配复杂场景', image: '/uploads/menu/menu_n80.png' }
|
||
]
|
||
},
|
||
{
|
||
key: 'N62',
|
||
label: 'N62',
|
||
products: [
|
||
{ name: 'N62', desc: 'Android11,高性能,适配复杂场景', image: '/uploads/menu/menu_n62.png' }
|
||
]
|
||
},
|
||
{
|
||
key: 'N6P',
|
||
label: 'N6P',
|
||
products: [
|
||
{ name: 'N6P', desc: 'Android13,高性能,适配复杂场景', image: '/uploads/menu/menu_n6p.png' }
|
||
]
|
||
},
|
||
{
|
||
key: 'N6',
|
||
label: 'N6',
|
||
products: [
|
||
{ name: 'N6', desc: 'Android7,高性能,适配复杂场景', image: '/uploads/menu/menu_n6.png' }
|
||
]
|
||
},
|
||
]
|
||
},
|
||
{
|
||
key: 'traditional',
|
||
label: '传统系列',
|
||
subs: [
|
||
{
|
||
key: 'k300',
|
||
label: 'K300',
|
||
products: [
|
||
{ name: 'K300', desc: '标准版,覆盖主流需求', image: '/uploads/menu/menu_k300.png' }
|
||
]
|
||
},
|
||
]
|
||
},
|
||
{
|
||
key: 'basic',
|
||
label: '基础系列',
|
||
subs: [
|
||
{
|
||
key: 'kd69',
|
||
label: 'KD69',
|
||
products: [
|
||
{ name: 'KD69', desc: '专业场景,扩展性强', image: '/uploads/menu/menu_kd69.png' },
|
||
]
|
||
},
|
||
]
|
||
}
|
||
];
|
||
|
||
const Navbar = () => {
|
||
const navigate = useNavigate();
|
||
const { user, logout } = useAuth();
|
||
const [search, setSearch] = useState('');
|
||
const [activeSeries, setActiveSeries] = useState(productMenu[0].key);
|
||
const [activeSub, setActiveSub] = useState(productMenu[0].subs[0].key);
|
||
const productsRef = useRef(null);
|
||
const [productsOpen, setProductsOpen] = useState(false);
|
||
const [productsSelected, setProductsSelected] = useState(false);
|
||
|
||
useEffect(() => {
|
||
const handleClickOutside = (e) => {
|
||
if (productsRef.current && !productsRef.current.contains(e.target)) {
|
||
setProductsOpen(false);
|
||
setProductsSelected(false);
|
||
}
|
||
};
|
||
document.addEventListener('mousedown', handleClickOutside);
|
||
return () => {
|
||
document.removeEventListener('mousedown', handleClickOutside);
|
||
};
|
||
}, []);
|
||
|
||
const handleLoginClick = () => {
|
||
navigate('/login');
|
||
};
|
||
|
||
const handleLogoutClick = () => {
|
||
logout();
|
||
navigate('/');
|
||
};
|
||
|
||
const handleSearchKeyDown = (e) => {
|
||
if (e.key === 'Enter') {
|
||
navigate('/');
|
||
}
|
||
};
|
||
|
||
return (
|
||
<nav className="navbar">
|
||
<div className="navbar-inner">
|
||
<div className="navbar-left">
|
||
<Link to="/" className="logo">
|
||
<img
|
||
src="/uploads/menu/logo.svg"
|
||
alt="Logo"
|
||
className="logo-img"
|
||
/>
|
||
</Link>
|
||
|
||
<div className={`nav-item ${productsOpen ? 'open' : ''} ${productsSelected ? 'selected' : ''}`} ref={productsRef}>
|
||
<span
|
||
className="nav-label"
|
||
onClick={() => {
|
||
setProductsOpen((prev) => {
|
||
const next = !prev;
|
||
setProductsSelected(next);
|
||
return next;
|
||
});
|
||
}}
|
||
>产品</span>
|
||
<div className="dropdown mega">
|
||
<div className="mega-col">
|
||
<div className="mega-title">系列</div>
|
||
<div className="mega-list">
|
||
{productMenu.map((series) => (
|
||
<button
|
||
key={series.key}
|
||
className={`mega-item ${series.key === activeSeries ? 'active' : ''}`}
|
||
onClick={() => {
|
||
setActiveSeries(series.key);
|
||
setActiveSub(series.subs[0]?.key || '');
|
||
}}
|
||
>
|
||
{series.label}
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div className="mega-col">
|
||
<div className="mega-title">型号</div>
|
||
<div className="mega-list">
|
||
{productMenu.find(s => s.key === activeSeries)?.subs.map((sub) => (
|
||
<button
|
||
key={sub.key}
|
||
className={`mega-item ${sub.key === activeSub ? 'active' : ''}`}
|
||
onClick={() => setActiveSub(sub.key)}
|
||
>
|
||
{sub.label}
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div className="mega-col mega-wide">
|
||
<div className="mega-title">介绍</div>
|
||
<div className="mega-products">
|
||
{productMenu
|
||
.find(s => s.key === activeSeries)
|
||
?.subs.find(sub => sub.key === activeSub)
|
||
?.products.map((p, idx) => (
|
||
<div
|
||
key={idx}
|
||
className="mega-product"
|
||
onClick={() => {
|
||
setProductsOpen(false);
|
||
navigate(`/product/${activeSeries}/${activeSub}/${idx}`, {
|
||
state: { product: p, series: activeSeries, sub: activeSub }
|
||
});
|
||
}}
|
||
style={{ cursor: 'pointer' }}
|
||
>
|
||
<img src={p.image} alt={p.name} />
|
||
<div className="mega-product-info">
|
||
<div className="name">{p.name}</div>
|
||
<div className="desc">{p.desc}</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* <div className="nav-item">
|
||
<span className="nav-label">解决方案</span>
|
||
<div className="dropdown">
|
||
<Link to="/" className="dropdown-item">解决方案A</Link>
|
||
<Link to="/" className="dropdown-item">解决方案B</Link>
|
||
<Link to="/" className="dropdown-item">解决方案C</Link>
|
||
</div>
|
||
</div> */}
|
||
|
||
{/* <div className="nav-item">
|
||
<span className="nav-label">行业</span>
|
||
<div className="dropdown">
|
||
<Link to="/" className="dropdown-item">民航</Link>
|
||
<Link to="/" className="dropdown-item">通航</Link>
|
||
<Link to="/" className="dropdown-item">研发制造</Link>
|
||
</div>
|
||
</div> */}
|
||
</div>
|
||
|
||
<div className="navbar-right">
|
||
<input
|
||
type="text"
|
||
className="search-input"
|
||
placeholder="搜索..."
|
||
value={search}
|
||
onChange={(e) => setSearch(e.target.value)}
|
||
onKeyDown={handleSearchKeyDown}
|
||
/>
|
||
|
||
{user ? (
|
||
<div className="user-area">
|
||
<span className="username">{user.name || user.username}</span>
|
||
<button className="btn btn-secondary" onClick={handleLogoutClick}>退出</button>
|
||
</div>
|
||
) : (
|
||
<button className="btn btn-primary" onClick={handleLoginClick}>登录</button>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
);
|
||
};
|
||
|
||
export default Navbar;
|