feat(example): 添加侧边菜单示例页面
- 更新 App.tsx 主应用布局和路由配置
- 更新 main.tsx 入口文件
- 新增 example/pages/side-menu/ 侧边菜单演示页面
Co-Authored-By: ClaudeCode
2 files modified
1 files added
| | |
| | | import { useState } from 'react'; |
| | | import type { ReactNode } from 'react'; |
| | | import { SideMenuPage } from './pages/side-menu/SideMenuPage'; |
| | | |
| | | /** 组件配置 */ |
| | | const components: Array<{ name: string; path: string; component: ReactNode }> = [ |
| | | { |
| | | name: 'CSideMenu', |
| | | path: '/pages/side-menu/SideMenuPage.tsx', |
| | | component: <SideMenuPage />, |
| | | }, |
| | | ]; |
| | | |
| | | /** |
| | | * 组件展示主页面 |
| | | * 左侧:组件列表 |
| | | * 右侧:iframe 展示组件示例 |
| | | */ |
| | | function App() { |
| | | const [activeIndex, setActiveIndex] = useState(0); |
| | | |
| | | return ( |
| | | <div style={{ padding: '20px' }}> |
| | | <h1>admin2-components</h1> |
| | | <p>组件展示示例(待开发)</p> |
| | | <div style={{ display: 'table', width: '100%', height: '100vh' }}> |
| | | {/* 左侧组件列表 */} |
| | | <div |
| | | style={{ |
| | | display: 'table-cell', |
| | | width: '200px', |
| | | borderRight: '1px solid #eee', |
| | | padding: '16px', |
| | | background: '#fafafa', |
| | | verticalAlign: 'top', |
| | | }} |
| | | > |
| | | <h3 style={{ marginTop: 0 }}>组件列表</h3> |
| | | <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}> |
| | | {components.map((comp, index) => ( |
| | | <li key={comp.name} style={{ marginBottom: '8px' }}> |
| | | <button |
| | | onClick={() => setActiveIndex(index)} |
| | | style={{ |
| | | width: '100%', |
| | | padding: '8px 12px', |
| | | textAlign: 'left', |
| | | background: activeIndex === index ? '#1890ff' : '#fff', |
| | | color: activeIndex === index ? '#fff' : '#333', |
| | | border: '1px solid #d9d9d9', |
| | | borderRadius: '4px', |
| | | cursor: 'pointer', |
| | | fontSize: '14px', |
| | | }} |
| | | > |
| | | {comp.name} |
| | | </button> |
| | | </li> |
| | | ))} |
| | | </ul> |
| | | </div> |
| | | |
| | | {/* 右侧 iframe 容器 */} |
| | | <div |
| | | style={{ |
| | | display: 'table-cell', |
| | | background: '#fff', |
| | | verticalAlign: 'top', |
| | | }} |
| | | > |
| | | <iframe |
| | | src={`http://localhost:5173/#/preview/${components[activeIndex].path}`} |
| | | style={{ |
| | | width: '100%', |
| | | height: '100%', |
| | | border: 'none', |
| | | }} |
| | | title={components[activeIndex].name} |
| | | /> |
| | | </div> |
| | | </div> |
| | | ); |
| | | } |
| | |
| | | import { createRoot } from 'react-dom/client'; |
| | | import './index.css'; |
| | | import App from './App'; |
| | | import { SideMenuPage } from './pages/side-menu/SideMenuPage'; |
| | | |
| | | createRoot(document.getElementById('root')!).render(<App />); |
| | | /** 预览页面 - 无 shell,直接渲染组件 */ |
| | | function PreviewPage() { |
| | | const hash = window.location.hash; |
| | | const path = hash.replace('#/preview/', ''); |
| | | |
| | | if (path.includes('side-menu')) { |
| | | return <SideMenuPage />; |
| | | } |
| | | |
| | | return <div>Unknown component</div>; |
| | | } |
| | | |
| | | const root = createRoot(document.getElementById('root')!); |
| | | |
| | | // 检查是否是预览模式 |
| | | if (window.location.hash.includes('/preview/')) { |
| | | root.render(<PreviewPage />); |
| | | } else { |
| | | root.render(<App />); |
| | | } |
| New file |
| | |
| | | import React, { useState, useEffect } from 'react'; |
| | | import { CSideMenu } from '../../../src'; |
| | | import type { MenuItem } from '../../../src/framework/sideMenu/types'; |
| | | |
| | | /** 模拟菜单数据 */ |
| | | const mockTree: MenuItem = { |
| | | key: '1', |
| | | label: '导航1', |
| | | type: 'folder', |
| | | children: [ |
| | | { |
| | | key: '1-1', |
| | | label: '子菜单1-1', |
| | | type: 'folder', |
| | | children: [ |
| | | { key: '1-1-1', label: '页面1-1-1', path: '/page1-1-1', pageName: 'Page111', type: 'file' }, |
| | | { key: '1-1-2', label: '页面1-1-2', path: '/page1-1-2', pageName: 'Page112', type: 'file' }, |
| | | ], |
| | | }, |
| | | { |
| | | key: '1-2', |
| | | label: '页面1-2', |
| | | path: '/page1-2', |
| | | pageName: 'Page12', |
| | | type: 'file', |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | /** 已打开的页面列表 */ |
| | | const mockPanesOnShelf = [ |
| | | { key: '1-1-1' }, |
| | | { key: '1-2' }, |
| | | ]; |
| | | |
| | | /** |
| | | * CSideMenu 组件示例页 |
| | | */ |
| | | export function SideMenuPage() { |
| | | const [collapsed, setCollapsed] = useState(false); |
| | | const [curActivePaneKey, setCurActivePaneKey] = useState<string | number>('1-1-1'); |
| | | const [isMobile, setIsMobile] = useState(false); |
| | | |
| | | // 检测移动端 - 与 CSideMenu 组件的判断逻辑一致 |
| | | useEffect(() => { |
| | | const checkMobile = () => { |
| | | const width = window.innerWidth; |
| | | const screenWidth = window.screen.width; |
| | | setIsMobile(width <= 992 && screenWidth <= 1024); |
| | | }; |
| | | checkMobile(); |
| | | window.addEventListener('resize', checkMobile); |
| | | return () => window.removeEventListener('resize', checkMobile); |
| | | }, []); |
| | | |
| | | const handleClickMenuItem = (item: MenuItem) => { |
| | | console.log('点击菜单项:', item); |
| | | setCurActivePaneKey(item.key); |
| | | }; |
| | | |
| | | const handleSetMenuCollapse = (value: boolean | void) => { |
| | | if (typeof value === 'boolean') { |
| | | setCollapsed(value); |
| | | } else { |
| | | setCollapsed((prev) => !prev); |
| | | } |
| | | }; |
| | | |
| | | return ( |
| | | <div style={{ display: 'flex', height: '100vh' }}> |
| | | <div style={{ flexShrink: 0 }}> |
| | | <CSideMenu |
| | | title="管理后台" |
| | | tree={mockTree} |
| | | collapsed={collapsed} |
| | | curActivePaneKey={curActivePaneKey} |
| | | panesOnShelf={mockPanesOnShelf} |
| | | onClickMenuItem={handleClickMenuItem} |
| | | onSetMenuCollapse={handleSetMenuCollapse} |
| | | /> |
| | | </div> |
| | | |
| | | <div style={{ flex: 1, padding: '20px', position: 'relative' }}> |
| | | {/* 移动端折叠/展开触发器 */} |
| | | {isMobile && ( |
| | | <button |
| | | onClick={() => handleSetMenuCollapse()} |
| | | style={{ |
| | | position: 'absolute', |
| | | top: '10px', |
| | | left: '10px', |
| | | zIndex: 100, |
| | | padding: '8px 12px', |
| | | background: '#1890ff', |
| | | color: '#fff', |
| | | border: 'none', |
| | | borderRadius: '4px', |
| | | cursor: 'pointer', |
| | | }} |
| | | > |
| | | {collapsed ? '展开菜单' : '收起菜单'} |
| | | </button> |
| | | )} |
| | | |
| | | <h2>CSideMenu 组件示例</h2> |
| | | <p>当前选中: {curActivePaneKey}</p> |
| | | <p>折叠状态: {collapsed ? '收起' : '展开'}</p> |
| | | </div> |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | export default SideMenuPage; |