Initial commit: 云印享后台管理系统

This commit is contained in:
2026-03-29 18:23:02 +08:00
commit f685a8aeed
23346 changed files with 2302962 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
.admin-layout {
min-height: 100vh;
}
.admin-sider {
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.06);
z-index: 10;
}
.logo {
height: 64px;
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid #f0f0f0;
padding: 0 16px;
}
.logo-icon {
font-size: 28px;
color: #1890ff;
}
.logo-text {
margin-left: 12px;
font-size: 20px;
font-weight: 600;
color: #1890ff;
}
.admin-menu {
border-right: none;
padding: 8px;
}
.admin-menu .ant-menu-item {
border-radius: 6px;
margin: 4px 0;
}
.admin-menu .ant-menu-item-selected {
background: linear-gradient(135deg, #1890ff 0%, #36cfc9 100%);
}
.admin-menu .ant-menu-item-selected a,
.admin-menu .ant-menu-item-selected .anticon {
color: #fff;
}
.admin-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
z-index: 9;
}
.trigger-btn {
font-size: 16px;
}
.header-right {
display: flex;
align-items: center;
gap: 16px;
}
.notification-btn {
font-size: 16px;
}
.user-info {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
padding: 4px 8px;
border-radius: 4px;
transition: background 0.3s;
}
.user-info:hover {
background: #f5f5f5;
}
.username {
font-size: 14px;
color: #262626;
}
.admin-content {
margin: 24px;
padding: 24px;
min-height: 280px;
overflow: auto;
}
@media (max-width: 768px) {
.admin-content {
margin: 12px;
padding: 16px;
}
}

View File

@@ -0,0 +1,140 @@
import { useState } from 'react'
import { Layout as AntLayout, Menu, Button, Avatar, Dropdown, Badge, theme } from 'antd'
import {
DashboardOutlined,
UserOutlined,
FileTextOutlined,
FolderOutlined,
DollarOutlined,
PrinterOutlined,
BarChartOutlined,
LogoutOutlined,
BellOutlined,
MenuFoldOutlined,
MenuUnfoldOutlined,
} from '@ant-design/icons'
import { Outlet, useNavigate, useLocation } from 'react-router-dom'
import './index.css'
const { Header, Sider, Content } = AntLayout
const Layout = () => {
const [collapsed, setCollapsed] = useState(false)
const navigate = useNavigate()
const location = useLocation()
const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken()
const menuItems = [
{
key: '/',
icon: <DashboardOutlined />,
label: '数据概览',
},
{
key: '/users',
icon: <UserOutlined />,
label: '用户管理',
},
{
key: '/orders',
icon: <FileTextOutlined />,
label: '订单管理',
},
{
key: '/files',
icon: <FolderOutlined />,
label: '文件管理',
},
{
key: '/prices',
icon: <DollarOutlined />,
label: '价目表管理',
},
{
key: '/settings',
icon: <PrinterOutlined />,
label: '打印设置',
},
{
key: '/statistics',
icon: <BarChartOutlined />,
label: '数据统计',
},
]
const handleMenuClick = (key: string) => {
navigate(key)
}
const handleLogout = () => {
localStorage.removeItem('admin_token')
navigate('/login')
}
const userMenuItems = [
{
key: 'logout',
icon: <LogoutOutlined />,
label: '退出登录',
onClick: handleLogout,
},
]
return (
<AntLayout className="admin-layout">
<Sider
trigger={null}
collapsible
collapsed={collapsed}
theme="light"
className="admin-sider"
>
<div className="logo">
<PrinterOutlined className="logo-icon" />
{!collapsed && <span className="logo-text"></span>}
</div>
<Menu
mode="inline"
selectedKeys={[location.pathname]}
items={menuItems}
onClick={({ key }) => handleMenuClick(key)}
className="admin-menu"
/>
</Sider>
<AntLayout>
<Header className="admin-header" style={{ background: colorBgContainer }}>
<Button
type="text"
icon={collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
onClick={() => setCollapsed(!collapsed)}
className="trigger-btn"
/>
<div className="header-right">
<Badge count={5} size="small">
<Button type="text" icon={<BellOutlined />} className="notification-btn" />
</Badge>
<Dropdown menu={{ items: userMenuItems }} placement="bottomRight">
<div className="user-info">
<Avatar icon={<UserOutlined />} size="small" />
<span className="username"></span>
</div>
</Dropdown>
</div>
</Header>
<Content
className="admin-content"
style={{
background: colorBgContainer,
borderRadius: borderRadiusLG,
}}
>
<Outlet />
</Content>
</AntLayout>
</AntLayout>
)
}
export default Layout