# BasicLayout.tsx 文档 ## 文件职责 `BasicLayout` 是应用的根布局组件,负责: 1. **整体页面结构**:定义应用的主要布局框架(品牌区、状态栏、导航区、内容区) 2. **响应式适配**:根据不同屏幕尺寸提供不同的导航方式和布局 3. **页面路由管理**:通过业务流程状态切换不同的页面组件 4. **全局布局配置**:支持配置化的布局选项(如品牌区和状态栏位置) ## 实现方式 ### 1. 技术栈 - **React**:组件化开发 - **Redux**:全局状态管理(业务流程状态) - **Ant Design**:布局系统(Layout、Row、Col、ConfigProvider) - **Ant Design Mobile**:移动端 TabBar - **Tailwind CSS**:响应式样式和工具类 ### 2. 核心组件结构 ``` BasicLayout ├── ConfigProvider (Ant Design 主题配置) └── Layout ├── Row (品牌和状态区域 - 可配置位置) │ ├── Col (品牌区域) │ └── Col (状态区域) ├── Row (主内容区域) │ ├── Col (导航区域 - 仅大屏显示) │ └── Col (内容区域) ├── Row (品牌和状态区域 - 底部位置) ├── TabBar (移动端底部导航 - 仅小屏显示) └── NavbarFloat (中等屏幕浮动导航) ``` ### 3. 响应式断点策略 | 屏幕尺寸 | 导航方式 | 品牌/状态栏 | | ------------ | ---------------- | ----------- | | xl (≥1200px) | 侧边 NavMenu | 显示 | | lg (≥992px) | 侧边 NavMenu | 显示 | | md (≥768px) | 浮动 NavbarFloat | 显示 | | sm (≥576px) | 底部 TabBar | 隐藏 | | xs (<576px) | 底部 TabBar | 隐藏 | ## 实现思路 ### 1. 页面映射机制 使用 `contentMap` 对象建立业务流程 key 与页面组件的映射关系: ```typescript const contentMap = { exam: , process: , view: , register: , worklist: , // ... 其他页面 }; ``` **优势**: - 集中管理所有页面路由 - 易于添加新页面 - 避免复杂的条件判断 ### 2. 状态驱动渲染 通过 Redux 的 `currentKey` 状态控制当前显示的页面: ```typescript const currentKey = useSelector( (state: RootState) => state.BusinessFlow.currentKey ); // 渲染对应页面 { contentMap[currentKey]; } ``` ### 3. 配置化布局 从配置文件读取布局参数,支持动态调整: ```typescript {pageLayoutConfig.brandAndStatusPosition === 'top' && ( 品牌和状态区域 )} ``` ### 4. 响应式导航策略 - **大屏(xl/lg)**:使用侧边栏 `NavMenu` - **中屏(md)**:使用浮动菜单 `NavbarFloat` - **小屏(sm/xs)**:使用底部 `TabBar` 通过 Tailwind CSS 的响应式工具类实现: ```typescript className = 'xl:hidden lg:hidden md:block'; ``` ### 5. 字体大小级联 使用父元素字体大小控制子元素(特别是图标)的尺寸: ```typescript className = 'xl:text-[48px] lg:text-[40px] md:text-[30px] ...'; ``` 子元素使用 `text-[100%]` 继承父元素字体大小,实现统一缩放。 ## 边界 ### 输入 - **Props**: - `children`:React.ReactNode(定义但未使用,保留用于扩展) - **Redux State**: - `currentKey`:当前业务流程标识(来自 `BusinessFlowSlice`) - **配置**: - `pageLayoutConfig`:页面布局配置(品牌/状态栏位置) ### 输出 - **渲染输出**:完整的应用布局结构,包含: - 品牌区域(Logo) - 状态栏(磁盘、电池、WiFi、热容量) - 导航菜单(根据屏幕尺寸选择不同形式) - 内容区域(根据 currentKey 渲染对应页面) - **事件派发**: - `setBusinessFlow(key)`:更新业务流程状态 ### 职责边界 #### 负责 - ✅ 整体布局结构定义 - ✅ 响应式适配逻辑 - ✅ 导航切换事件处理 - ✅ 页面组件渲染 - ✅ 布局配置应用 #### 不负责 - ❌ 具体页面的业务逻辑(由各页面组件负责) - ❌ 状态栏数据获取(使用静态数据,实际数据由 StatusBar 组件处理) - ❌ 用户权限验证(由上层路由或页面组件处理) - ❌ 国际化内容翻译(TabBar 的文本是硬编码的) ## 涉及概念 ### 1. 响应式布局(Responsive Layout) 通过 CSS 媒体查询和响应式工具类,使页面在不同屏幕尺寸下有不同表现。 **实现方式**: - Ant Design 的 Grid 系统(Col 组件的 xl/lg/md/sm/xs 属性) - Tailwind CSS 的响应式前缀(xl:/lg:/md:/sm:/xs:) ### 2. Grid 系统 将页面分为 24 列,通过 `Col` 组件的 `span` 值控制宽度。 **示例**: ```typescript // 大屏占4列,小屏隐藏 // 大屏占20列,小屏隐藏 ``` ### 3. 映射表模式(Map Pattern) 使用对象字面量建立 key-value 映射,替代多个 if-else 或 switch 语句。 **优势**: - 代码更简洁易读 - 易于维护和扩展 - 性能更好(O(1) 查找) ### 4. 状态驱动视图(State-Driven View) 视图完全由状态决定,状态改变自动触发视图更新。 **流程**: ``` 用户点击导航 → dispatch(setBusinessFlow) → currentKey 更新 → 组件重新渲染 → 显示新页面 ``` ### 5. 条件渲染(Conditional Rendering) 根据条件决定是否渲染某个组件或元素。 **方式**: - 逻辑与运算符:`{condition && }` - 三元运算符:`{condition ? : }` - CSS 类名控制:`className="xl:block sm:hidden"` ### 6. Flexbox 布局 使用 CSS Flexbox 实现灵活的布局方式。 **关键属性**: - `flex: 1`:占据剩余空间 - `display: flex`:启用 flex 布局 - `justify-end`:主轴末端对齐 - `items-center`:交叉轴居中对齐 ### 7. 配置化(Configuration) 将可变的参数提取到配置文件,提高代码的可维护性和灵活性。 **示例**: ```typescript // 配置文件 export const pageLayoutConfig = { brandAndStatusPosition: 'top' // 或 'bottom' }; // 使用配置 {pageLayoutConfig.brandAndStatusPosition === 'top' && ...} ``` ### 8. 组件组合(Component Composition) 将大型组件拆分为多个小型、专注的组件,通过组合构建完整功能。 **本文件中的组件组合**: - `NavMenu`:侧边导航菜单 - `NavbarFloat`:浮动导航菜单 - `StatusBar`:状态栏 - `TabBar`:底部标签栏 - 各个页面组件(RegisterPage、ExamPage 等) ## 注意事项 ### 1. 硬编码问题 - **状态栏数据**:使用了硬编码的静态数据 ```typescript const status: StatusBarProps = { diskStatus: 'available', batteryLevel: 0, wifiStrength: 0, heatCapacity: 0, }; ``` **改进建议**:应该从实际的状态或 Redux store 中获取 - **TabBar 文本**:未使用国际化 ```typescript ``` **改进建议**:应该使用 i18n 系统 ### 2. 未使用的 Props `children` prop 被定义但未使用,可能是为了未来扩展预留。 ### 3. 重复代码 品牌和状态区域的代码重复了两次(top 和 bottom 位置),可以提取为独立组件。 ### 4. TODO 项 代码中存在 TODO 注释,需要后续完善: - MeButton 的登录状态和头像应该从实际状态获取 ### 5. 响应式字体大小策略 通过顶层 Layout 设置字体大小,子元素使用 `text-[100%]` 继承,实现整体缩放。这是一个巧妙的设计,但需要确保所有子组件都支持这种方式。 ## 相关文件 - `src/layouts/NavMenu.tsx`:侧边导航菜单组件 - `src/layouts/NavbarFloat.tsx`:浮动导航菜单组件 - `src/layouts/StateBar.tsx`:状态栏组件 - `src/states/BusinessFlowSlice.ts`:业务流程状态切片 - `src/config/pageLayout.ts`:页面布局配置 - `src/pages/*`:各个页面组件