130 lines
3.7 KiB
TypeScript
130 lines
3.7 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { Link, Outlet, useNavigate } from 'umi';
|
|
import { Layout as AntLayout, Input, Button, Avatar, Dropdown, Menu, Space, Badge } from 'antd';
|
|
import { SearchOutlined, UserOutlined, BellOutlined, BookOutlined, MessageOutlined } from '@ant-design/icons';
|
|
import { userApi } from '../services/api';
|
|
import type { User } from '../services/mockData';
|
|
import styles from './index.less';
|
|
|
|
const { Header, Content } = AntLayout;
|
|
|
|
export default function Layout() {
|
|
const navigate = useNavigate();
|
|
const [searchValue, setSearchValue] = useState('');
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
// 获取用户信息
|
|
userApi.getCurrentUser().then(res => {
|
|
if (res.success) {
|
|
setUser(res.data);
|
|
}
|
|
});
|
|
}, []);
|
|
|
|
const handleSearch = () => {
|
|
if (searchValue.trim()) {
|
|
navigate(`/?search=${encodeURIComponent(searchValue)}`);
|
|
}
|
|
};
|
|
|
|
const handleKeyPress = (e: React.KeyboardEvent) => {
|
|
if (e.key === 'Enter') {
|
|
handleSearch();
|
|
}
|
|
};
|
|
|
|
const userMenu = (
|
|
<Menu>
|
|
<Menu.Item key="profile">
|
|
<UserOutlined /> 个人中心
|
|
</Menu.Item>
|
|
<Menu.Item key="settings">
|
|
设置
|
|
</Menu.Item>
|
|
<Menu.Divider />
|
|
<Menu.Item key="logout">
|
|
退出登录
|
|
</Menu.Item>
|
|
</Menu>
|
|
);
|
|
|
|
return (
|
|
<AntLayout className={styles.layout}>
|
|
<Header className={styles.header}>
|
|
<div className={styles.headerContent}>
|
|
{/* Logo区域 */}
|
|
<div className={styles.logo}>
|
|
<Link to="/" className={styles.logoLink}>
|
|
AutoBeeAgent
|
|
</Link>
|
|
</div>
|
|
|
|
{/* 搜索框 */}
|
|
<div className={styles.search}>
|
|
<Input
|
|
placeholder="搜索热门话题..."
|
|
value={searchValue}
|
|
onChange={(e) => setSearchValue(e.target.value)}
|
|
onKeyPress={handleKeyPress}
|
|
prefix={<SearchOutlined />}
|
|
// suffix={
|
|
// <Button
|
|
// type="primary"
|
|
// size="small"
|
|
// onClick={handleSearch}
|
|
// loading={loading}
|
|
// >
|
|
// AI搜索
|
|
// </Button>
|
|
// }
|
|
/>
|
|
</div>
|
|
|
|
{/* 用户信息 */}
|
|
<div className={styles.userInfo}>
|
|
<Space size="middle">
|
|
<Button type="text" icon={<BookOutlined />}>
|
|
学习
|
|
</Button>
|
|
<Badge count={0}>
|
|
<Button type="text" icon={<BellOutlined />}>
|
|
消息
|
|
</Button>
|
|
</Badge>
|
|
{user ? (
|
|
<Dropdown overlay={userMenu} placement="bottomRight">
|
|
<div className={styles.userProfile}>
|
|
<Avatar src={user.avatar} icon={<UserOutlined />} />
|
|
<span className={styles.userName}>{user.name}</span>
|
|
</div>
|
|
</Dropdown>
|
|
) : (
|
|
<Button type="primary" onClick={() => navigate('/login')}>
|
|
登录
|
|
</Button>
|
|
)}
|
|
</Space>
|
|
</div>
|
|
</div>
|
|
</Header>
|
|
|
|
<Content className={styles.content}>
|
|
<Outlet />
|
|
</Content>
|
|
|
|
{/* 浮动客服按钮 */}
|
|
<div className={styles.floatingService}>
|
|
<Button
|
|
type="primary"
|
|
shape="circle"
|
|
icon={<MessageOutlined />}
|
|
size="large"
|
|
className={styles.serviceButton}
|
|
/>
|
|
</div>
|
|
</AntLayout>
|
|
);
|
|
}
|