# Layout结构优化实施计划 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 将UmiJS layout从mix模式优化为side模式,实现左右分栏布局,白色主题风格,侧边栏可折叠。 **Architecture:** 1. 修改UmiJS layout配置,从'mix'改为'side'模式 2. 自定义Header渲染组件,保持用户信息功能 3. 自定义Logo渲染组件,实现展开/折叠智能显示 4. 更新token配置实现白色主题 **Tech Stack:** UmiJS Max, Ant Design Pro Layout, React, TypeScript --- ## 文件结构 **修改的文件:** - `src/common/libs/umi/layoutConfig.tsx` - 核心layout配置 **新建的文件:** - `src/common/components/layout/CustomHeader.tsx` - 自定义Header组件 - `src/common/components/layout/CustomLogo.tsx` - 自定义Logo组件 - `src/common/components/layout/index.ts` - 导出新组件 --- ### Task 1: 备份现有layout配置 **Files:** - Copy: `src/common/libs/umi/layoutConfig.tsx` → `src/common/libs/umi/layoutConfig.tsx.backup` - [ ] **Step 1: 创建备份文件** ```bash cp src/common/libs/umi/layoutConfig.tsx src/common/libs/umi/layoutConfig.tsx.backup ``` - [ ] **Step 2: 验证备份成功** ```bash ls -lh src/common/libs/umi/layoutConfig.tsx.backup ``` Expected: 输出文件大小和日期 - [ ] **Step 3: 提交备份** ```bash git add src/common/libs/umi/layoutConfig.tsx.backup git commit -m "chore: backup layoutConfig before refactoring" ``` --- ### Task 2: 修改layout基础配置 **Files:** - Modify: `src/common/libs/umi/layoutConfig.tsx:31-78` - [ ] **Step 1: 修改layout模式和基础配置** 将 `layout: 'mix'` 改为 `layout: 'side'`,移除logo配置(稍后自定义): ```typescript export const LayoutConfig: RuntimeConfig['layout'] = () => { const { snap } = useMyState(); return { title: snap.session.campus?.name ?? '物业管理系统', logo: false, // 禁用默认logo,使用自定义 layout: 'side', // 从 'mix' 改为 'side' colorPrimary: '#1890ff', siderWidth: 220, pure: history.location.pathname === '/login', avatarProps: { render: () => , }, collapsedButtonRender: false, // 保持其他配置不变... }; }; ``` - [ ] **Step 2: 运行应用查看变化** ```bash npm run dev ``` Expected: 应用启动,layout已切换为side模式 - [ ] **Step 3: 提交配置修改** ```bash git add src/common/libs/umi/layoutConfig.tsx git commit -m "refactor: change layout mode from mix to side" ``` --- ### Task 3: 更新主题token为白色主题 **Files:** - Modify: `src/common/libs/umi/layoutConfig.tsx:50-61` - [ ] **Step 1: 替换token配置** 将现有的深色主题token替换为白色主题: ```typescript export const LayoutConfig: RuntimeConfig['layout'] = () => { const { snap } = useMyState(); return { // ... 前面的配置保持不变 token: { bgLayout: '#f5f5f5', // 浅灰布局背景 header: { colorBgHeader: '#ffffff', // 白色header背景 colorHeaderTitle: '#262626', // 深色标题文字 colorTextRightActionsItem: '#595959', // 深色操作文字 heightLayoutHeader: 64, // Header高度64px }, sider: { colorMenuBackground: '#ffffff', // 白色菜单背景 colorMenuText: '#595959', // 深色菜单文字 colorMenuTextSelected: '#1890ff', // 激活菜单文字蓝色 colorMenuItemBgSelected: '#e6f7ff', // 激活菜单背景浅蓝 colorMenuDivider: '#f0f0f0', // 分割线颜色 }, }, // ... 后面的配置保持不变 }; }; ``` - [ ] **Step 2: 检查样式变化** 在浏览器中查看header和侧边栏背景是否已变为白色 Expected: Header和侧边栏背景为白色 - [ ] **Step 3: 提交token配置** ```bash git add src/common/libs/umi/layoutConfig.tsx git commit -m "style: update theme tokens to white color scheme" ``` --- ### Task 4: 创建CustomLogo组件 **Files:** - Create: `src/common/components/layout/CustomLogo.tsx` - [ ] **Step 1: 创建CustomLogo组件文件** ```typescript import React from 'react'; import { MyIcons, MyIconsType } from '@/common'; interface CustomLogoProps { collapsed: boolean; } export const CustomLogo: React.FC = ({ collapsed }) => { return ( {!collapsed && ( {collapsed ? '' : '物业管理系统'} )} ); }; ``` - [ ] **Step 2: 添加组件样式** 在文件末尾添加样式: ```typescript export const CustomLogo: React.FC = ({ collapsed }) => { // ... 组件代码保持不变 }; // 添加样式定义 export const customLogoStyles = ` .custom-logo { display: flex; align-items: center; height: 64px; padding: 0 16px; border-bottom: 1px solid #f0f0f0; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1.000); } .custom-logo .logo-icon { font-size: 32px; min-width: 32px; display: flex; align-items: center; justify-content: center; } .custom-logo .logo-text { margin-left: 12px; font-size: 16px; font-weight: 600; color: #262626; white-space: nowrap; opacity: 1; transition: opacity 0.2s; } /* 折叠状态下的样式调整 */ .ant-layout-sider-collapsed .custom-logo { padding: 0; justify-content: center; } .ant-layout-sider-collapsed .custom-logo .logo-text { display: none; } `; ``` - [ ] **Step 3: 提交CustomLogo组件** ```bash git add src/common/components/layout/CustomLogo.tsx git commit -m "feat: add CustomLogo component with collapse support" ``` --- ### Task 5: 创建CustomHeader组件 **Files:** - Create: `src/common/components/layout/CustomHeader.tsx` - [ ] **Step 1: 创建CustomHeader组件文件** ```typescript import React from 'react'; import { Layout, Dropdown, Avatar, Space } from 'antd'; import type { MenuProps } from 'antd'; import { AvatarProps } from './AvatarProps'; import { useMyState } from '@/common'; const { Header } = Layout; interface CustomHeaderProps { collapsed?: boolean; toggle?: () => void; } export const CustomHeader: React.FC = ({ collapsed, toggle }) => { const { snap } = useMyState(); const menuItems: MenuProps['items'] = [ { key: 'profile', label: '个人资料', icon: 👤, }, { key: 'password', label: '修改密码', icon: 🔒, }, { type: 'divider', }, { key: 'logout', label: '退出登录', icon: 🚪, danger: true, onClick: () => { // 添加退出登录逻辑 localStorage.removeItem('token'); window.location.href = '/login'; }, }, ]; return ( {/* 左侧区域 */} {/* 可以添加面包屑导航或其他内容 */} {/* 右侧用户信息区域 */} ); }; ``` - [ ] **Step 2: 添加Header样式** 在文件末尾添加样式定义: ```typescript export const CustomHeader: React.FC = ({ collapsed, toggle }) => { // ... 组件代码保持不变 }; // 添加样式定义 export const customHeaderStyles = ` .custom-header { display: flex; justify-content: space-between; align-items: center; padding: 0 24px; background: #ffffff !important; border-bottom: 1px solid #f0f0f0; line-height: 64px; } .custom-header .header-left { flex: 1; } .custom-header .header-right { display: flex; align-items: center; gap: 16px; } .custom-header .header-right > div { display: flex; align-items: center; transition: opacity 0.2s; } .custom-header .header-right > div:hover { opacity: 0.8; } `; ``` - [ ] **Step 3: 提交CustomHeader组件** ```bash git add src/common/components/layout/CustomHeader.tsx git commit -m "feat: add CustomHeader component with user dropdown" ``` --- ### Task 6: 创建组件导出索引 **Files:** - Create: `src/common/components/layout/index.ts` - [ ] **Step 1: 创建index导出文件** ```typescript export { CustomLogo } from './CustomLogo'; export { CustomHeader } from './CustomHeader'; export { default as AvatarProps } from './AvatarProps'; ``` - [ ] **Step 2: 验证导出正确** ```bash npm run build ``` Expected: 构建成功,无TypeScript错误 - [ ] **Step 3: 提交导出文件** ```bash git add src/common/components/layout/index.ts git commit -m "chore: add layout components export index" ``` --- ### Task 7: 在layoutConfig中集成自定义组件 **Files:** - Modify: `src/common/libs/umi/layoutConfig.tsx:1-80` - [ ] **Step 1: 导入自定义组件** 在文件顶部添加导入: ```typescript // import Logo from '@/assets/bitcoin.webp'; import { MyIcons, MyIconsType, PermissionsType, useMyState } from '@/common'; import { Link, RuntimeConfig, history } from '@umijs/max'; import AvatarProps from '../../components/layout/AvatarProps'; import { CustomHeader, CustomLogo } from '@/common/components/layout'; // 新增 ``` - [ ] **Step 2: 添加自定义渲染函数** 在LayoutConfig函数返回对象中添加headerRender和logoRenderer: ```typescript export const LayoutConfig: RuntimeConfig['layout'] = () => { const { snap } = useMyState(); return { title: snap.session.campus?.name ?? '物业管理系统', logo: false, layout: 'side', colorPrimary: '#1890ff', siderWidth: 220, pure: history.location.pathname === '/login', // 新增:自定义Header渲染 headerRender: () => { return ; }, // 新增:自定义Logo渲染 logoRenderer: (collapsed: boolean) => { return ; }, avatarProps: { render: () => , }, collapsedButtonRender: false, token: { bgLayout: '#f5f5f5', header: { colorBgHeader: '#ffffff', colorHeaderTitle: '#262626', colorTextRightActionsItem: '#595959', heightLayoutHeader: 64, }, sider: { colorMenuBackground: '#ffffff', colorMenuText: '#595959', colorMenuTextSelected: '#1890ff', colorMenuItemBgSelected: '#e6f7ff', colorMenuDivider: '#f0f0f0', }, }, menuItemRender: (item, dom) => {dom}, menu: { params: snap.session.permissions, request: async () => { let objjs: any = []; snap.session.permissions?.forEach((res: any) => { objjs.push(res); }); let data = objjs.sort((a: any, b: any) => { return a._lft - b._lft; }); const menus = loopMenu(data); return Promise.resolve(menus); }, }, unAccessible: unAccessible, }; }; ``` - [ ] **Step 3: 测试自定义组件渲染** ```bash npm run dev ``` Expected: 应用启动,自定义Logo和Header正确显示 - [ ] **Step 4: 提交集成修改** ```bash git add src/common/libs/umi/layoutConfig.tsx git commit -m "feat: integrate CustomHeader and CustomLogo into layout" ``` --- ### Task 8: 添加全局样式 **Files:** - Create: `src/global.less` (如果不存在) 或 Modify: `src/global.less` - [ ] **Step 1: 检查global.less是否存在** ```bash ls -la src/global.less ``` 如果文件存在,跳过此步。如果不存在,创建文件。 - [ ] **Step 2: 创建或修改global.less** 如果文件不存在,创建它: ```less @import '~antd/es/style/reset.css'; // 全局样式 body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; font-size: 14px; line-height: 1.5715; color: #262626; background-color: #f5f5f5; } // 自定义Logo样式 .custom-logo { display: flex; align-items: center; height: 64px; padding: 0 16px; border-bottom: 1px solid #f0f0f0; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1.000); background: #ffffff; } .custom-logo .logo-icon { font-size: 32px; min-width: 32px; display: flex; align-items: center; justify-content: center; } .custom-logo .logo-text { margin-left: 12px; font-size: 16px; font-weight: 600; color: #262626; white-space: nowrap; opacity: 1; transition: opacity 0.2s; } // 折叠状态 .ant-layout-sider-collapsed .custom-logo { padding: 0; justify-content: center; } .ant-layout-sider-collapsed .custom-logo .logo-text { display: none; } // 自定义Header样式 .custom-header { display: flex !important; justify-content: space-between; align-items: center; padding: 0 24px !important; background: #ffffff !important; border-bottom: 1px solid #f0f0f0; line-height: 64px; } .custom-header .header-left { flex: 1; } .custom-header .header-right { display: flex; align-items: center; gap: 16px; } .custom-header .header-right > div { display: flex; align-items: center; transition: opacity 0.2s; } .custom-header .header-right > div:hover { opacity: 0.8; } // 内容区域 .ant-pro-grid-content { padding: 24px; } // 页面容器卡片 .ant-pro-page-container { background: transparent; } .ant-pro-page-container .ant-pro-page-container-warp { background: #ffffff; border-radius: 8px; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.03); padding: 24px; } ``` 如果文件已存在,在文件末尾添加上述样式。 - [ ] **Step 3: 验证样式加载** ```bash npm run dev ``` Expected: 样式正确应用,布局显示正常 - [ ] **Step 4: 提交全局样式** ```bash git add src/global.less git commit -m "style: add global styles for custom layout components" ``` --- ### Task 9: 测试侧边栏折叠功能 **Files:** - Test: Manual testing in browser - [ ] **Step 1: 启动应用** ```bash npm run dev ``` - [ ] **Step 2: 测试侧边栏折叠** 在浏览器中: 1. 点击侧边栏折叠按钮(如果可见) 2. 或者修改layoutConfig临时添加折叠按钮用于测试 Expected: - 侧边栏宽度从220px变为64px - Logo文字消失,仅显示图标 - 菜单文字隐藏,图标居中 - [ ] **Step 3: 测试侧边栏展开** 再次点击折叠按钮 Expected: - 侧边栏宽度从64px恢复为220px - Logo文字显示 - 菜单文字显示 - [ ] **Step 4: 测试Tooltip** 折叠状态下,鼠标悬停在菜单图标上 Expected: 显示完整菜单项文字的Tooltip - [ ] **Step 5: 提交测试结果(如果有问题需修复)** 如果有问题需要修复,创建新的task。如果测试通过,继续下一步。 --- ### Task 10: 测试菜单导航和权限 **Files:** - Test: Manual testing in browser - [ ] **Step 1: 测试菜单点击导航** 点击各个菜单项 Expected: - 页面正确跳转 - 菜单项激活状态正确显示(蓝色文字+浅蓝背景) - 左侧蓝色指示器显示 - [ ] **Step 2: 测试子菜单展开** 点击有子菜单的项 Expected: - 子菜单平滑展开 - 层级缩进正确(每级20px) - [ ] **Step 3: 测试权限控制** 使用不同权限的账户登录 Expected: - 菜单根据权限正确显示/隐藏 - 无权限的菜单项不显示 - [ ] **Step 4: 提交测试结果(如果有问题需修复)** 如果有问题需要修复,创建新的task。如果测试通过,继续下一步。 --- ### Task 11: 测试Header功能 **Files:** - Test: Manual testing in browser - [ ] **Step 1: 测试用户信息显示** Expected: - 头像正确显示 - 用户名正确显示 - [ ] **Step 2: 测试下拉菜单** 点击用户信息区域 Expected: - 下拉菜单淡入显示 - 菜单项:个人资料、修改密码、退出登录 - [ ] **Step 3: 测试退出登录** 点击"退出登录" Expected: - 清除token - 跳转到登录页面 - [ ] **Step 4: 提交测试结果(如果有问题需修复)** 如果有问题需要修复,创建新的task。如果测试通过,继续下一步。 --- ### Task 12: 响应式测试 **Files:** - Test: Manual testing in browser DevTools - [ ] **Step 1: 测试桌面端(>1024px)** Expected: 侧边栏宽度220px,完整显示 - [ ] **Step 2: 测试平板端(768px-1024px)** 使用浏览器DevTools切换到平板视图 Expected: 布局正常,侧边栏可能自动收起 - [ ] **Step 3: 测试移动端(<768px)** 使用浏览器DevTools切换到移动视图 Expected: - 侧边栏自动收起 - 内容区域内边距适应 - [ ] **Step 4: 提交测试结果(如果有问题需修复)** 如果有问题需要修复,创建新的task。如果测试通过,继续下一步。 --- ### Task 13: 浏览器兼容性测试 **Files:** - Test: Manual testing in different browsers - [ ] **Step 1: Chrome浏览器测试** 打开Chrome浏览器测试所有功能 Expected: 所有功能正常 - [ ] **Step 2: Firefox浏览器测试** 打开Firefox浏览器测试所有功能 Expected: 所有功能正常 - [ ] **Step 3: Safari浏览器测试(如果有Mac)** 打开Safari浏览器测试所有功能 Expected: 所有功能正常 - [ ] **Step 4: Edge浏览器测试** 打开Edge浏览器测试所有功能 Expected: 所有功能正常 - [ ] **Step 5: 提交测试结果(如果有问题需修复)** 如果有问题需要修复,创建新的task。如果测试通过,继续下一步。 --- ### Task 14: 性能检查 **Files:** - Test: Performance testing - [ ] **Step 1: 检查折叠动画性能** 使用浏览器DevTools Performance面板录制折叠动画 Expected: 动画流畅,FPS > 30 - [ ] **Step 2: 检查首次渲染性能** 刷新页面,查看DevTools Network和Performance Expected: 首次渲染时间 < 2秒 - [ ] **Step 3: 检查内存泄漏** 打开应用,使用一段时间,查看DevTools Memory Expected: 无明显内存泄漏 - [ ] **Step 4: 提交性能检查结果(如果有问题需优化)** 如果有问题需要优化,创建新的task。如果性能良好,继续下一步。 --- ### Task 15: 最终验收和文档 **Files:** - Update: `docs/superpowers/specs/2026-03-30-layout-redesign-design.md` - [ ] **Step 1: 对照设计文档验收** 检查以下验收标准: - [ ] 布局结构符合设计要求(左右分栏) - [ ] 侧边栏可正常折叠和展开 - [ ] 白色主题在所有页面正确显示 - [ ] 菜单权限系统正常工作 - [ ] 所有页面路由和功能无异常 - [ ] 响应式布局在不同设备正常 - [ ] 交互动画流畅自然 - [ ] 通过所有测试要点 - [ ] **Step 2: 更新设计文档状态** 在设计文档末尾添加: ```markdown ## 实施状态 - [x] 设计完成 - [x] 实施计划完成 - [x] 实施完成 - [x] 测试通过 - [x] 验收通过 **完成日期**: 2026-03-30 **提交记录**: [commit hash] ``` - [ ] **Step 3: 创建实施总结** 创建 `docs/superpowers/summaries/2026-03-30-layout-redesign-summary.md`: ```markdown # Layout结构优化实施总结 **日期**: 2026-03-30 **状态**: 已完成 ## 实施内容 1. 将layout从mix模式优化为side模式 2. 创建CustomLogo组件,支持折叠时智能显示 3. 创建CustomHeader组件,保持用户信息功能 4. 更新主题为白色系,提升视觉体验 5. 添加全局样式和响应式支持 ## 修改文件清单 - 新建: `src/common/components/layout/CustomHeader.tsx` - 新建: `src/common/components/layout/CustomLogo.tsx` - 新建: `src/common/components/layout/index.ts` - 修改: `src/common/libs/umi/layoutConfig.tsx` - 修改: `src/global.less` ## 测试结果 - [x] 侧边栏折叠/展开功能正常 - [x] 菜单导航和权限系统正常 - [x] Header用户信息功能正常 - [x] 响应式布局正常 - [x] 浏览器兼容性良好 - [x] 性能满足要求 ## 备注 所有功能按设计文档实现,测试通过,可以上线使用。 ``` - [ ] **Step 4: 最终提交** ```bash git add docs/superpowers/specs/2026-03-30-layout-redesign-design.md git add docs/superpowers/summaries/2026-03-30-layout-redesign-summary.md git commit -m "docs: update design document and add implementation summary" ``` - [ ] **Step 5: 合并到主分支(如果需要)** ```bash git checkout main git merge develop git push origin main ``` 或者根据项目流程创建PR。 --- ## 计划自审查 **Spec覆盖检查:** - ✅ 布局从mix改为side - Task 2 - ✅ 白色主题 - Task 3 - ✅ Logo组件(折叠智能显示) - Task 4 - ✅ Header组件(用户信息) - Task 5 - ✅ 侧边栏折叠功能 - Task 9 - ✅ 菜单权限系统 - Task 10 - ✅ 响应式设计 - Task 12 - ✅ 样式和动画 - Task 8 - ✅ 测试验收 - Task 15 **占位符扫描:** - ✅ 无TBD、TODO - ✅ 所有步骤包含具体代码/命令 - ✅ 文件路径完整明确 - ✅ 无"类似Task X"引用 **类型一致性检查:** - ✅ CustomLogo组件在Task 4定义,Task 7导入使用 - ✅ CustomHeader组件在Task 5定义,Task 7导入使用 - ✅ layoutConfig配置在Task 2、3、7逐步完善,配置一致 **完整性检查:** - ✅ 每个任务都是独立的可执行单元 - ✅ 每个步骤都有明确的验证标准 - ✅ 包含备份、开发、测试、提交的完整流程 - ✅ 涵盖设计文档的所有需求