flnxi-Wu/优化记录.md
WuYongJie 7dc8d2a528
Some checks failed
CI Check / check (push) Has been cancelled
feat: 统一弹窗系统 & 首页UI优化
- 替换所有浏览器原生弹窗(confirm/alert/prompt)
  - 创建 ConfirmDialog、AlertDialog、PromptDialog 组件
  - 创建 DialogProvider 和 useDialog Hook
  - 替换所有 admin 组件、首页、分享页面中的原生弹窗

- 素材预览面板统一
  - 创建 MaterialPreviewModal 组件
  - 使用统一弹窗组件,统一退出逻辑

- 首页UI统一到三层架构
  - 迁移主要按钮和输入框样式
  - 迁移筛选弹窗中的所有按钮样式
  - 使用 useThemeStyles() Hook

- 更新文档
  - 更新优化记录、优化计划、后续修改、更新日志
2025-11-22 16:20:05 +08:00

19 KiB
Raw Blame History

Admin 页面优化建议和问题修复记录

✅ 已完成的修复

1. 类型定义统一化

  • ✅ 创建了 types.ts 统一管理所有类型定义
  • ✅ 移除了 page.tsx 中的重复类型定义(User, Material, Category, Scene, Platform, Invitation, UserTreeNode, DepartmentNode, DepartmentUserGrouping)
  • ✅ 移除了 TemplateManager.tsx 中的重复 ToastFn 定义
  • ✅ 添加了 AdminTab 类型统一管理 Tab 类型
  • ✅ 添加了 DashboardData 接口用于监控仪表板数据
  • ✅ 修复了 TemplateManager.tsx 中 DragHoverState 的类型错误(fallback 对象的 position 属性需要明确类型为 'before' | 'after')
  • ✅ 修复了 TemplateFieldsEditor.tsx 中 onFieldDragOver 回调签名,添加缺失的 surface 参数
  • ✅ 修复了 UsersTab.tsx 中 showTransferButton 在使用前未定义的问题,将其改为 useMemo 并移到使用前定义

2. UI 样式统一化 - 三层架构重构

  • ✅ 创建了三层架构的样式系统:
    • 基础层:lib/ui-styles-base.ts - 包含布局、大小、动画等非颜色样式
    • 颜色层:lib/ui-theme-colors-light.ts / dark.ts - 仅包含颜色配置
    • 组合层:lib/ui-styles-composer.ts - 自动组合基础样式和颜色主题
    • 导出层:lib/ui-styles-light.ts / dark.ts - 最终导出的样式(由组合器生成)
  • ✅ 创建了 lib/hooks/useThemeStyles.ts - 主题感知的样式 Hook
    • useThemeStyles() - 根据当前主题自动返回对应的样式配置
    • useTheme() - 获取当前主题状态
  • ✅ 保持了向后兼容性:
    • 原有的 lib/ui-styles.ts 仍然保留(包含 dark: 前缀的样式)
    • 新组件推荐使用 useThemeStyles() Hook
    • 旧组件可以继续使用原有导入,逐步迁移

核心优势:

  • ✅ 统一视觉设计:修改布局、大小、动画时,只需修改 ui-styles-base.ts 一处,浅色和深色模式自动同步
  • ✅ 独立颜色适配:颜色配置完全分离,可以独立调整浅色或深色模式的颜色
  • ✅ 易于维护:清晰的职责分离,修改时不会遗漏或出错
  • ✅ 类型安全:TypeScript 类型检查确保配置正确

修改指南:

  • 修改布局/大小/动画 → 修改 lib/ui-styles-base.ts(一处修改,两套主题自动同步)
  • 修改浅色模式颜色 → 修改 lib/ui-theme-colors-light.ts
  • 修改深色模式颜色 → 修改 lib/ui-theme-colors-dark.ts

架构文档: 详见 docs/guides/UI_STYLES_ARCHITECTURE.md

使用示例:

'use client'
import { useThemeStyles } from '@/lib/ui-styles'

export default function MyComponent() {
  const styles = useThemeStyles()
  
  return (
    <div className={styles.cardStyles.base}>
      <button className={styles.buttonStyles.primary}>点击</button>
    </div>
  )
}

迁移进度:

  • ✅ 基础 UI 组件已迁移:
    • LoadingState.tsx - 使用 useThemeStyles() 和 useTheme()
    • ErrorState.tsx - 使用 useThemeStyles() 和 useTheme()
    • EmptyState.tsx - 使用 useTheme() 根据主题选择文字颜色
  • ✅ Tab 组件迁移(全部完成):
    • MaterialsTab.tsx - 完全迁移到新样式系统,移除了所有 dark: 前缀
    • CategoriesTab.tsx - 完全迁移到新样式系统,移除了所有 dark: 前缀
    • InvitationsTab.tsx - 完全迁移到新样式系统,移除了所有 dark: 前缀
    • DepartmentsTab.tsx - 完全迁移到新样式系统,移除了所有 dark: 前缀
    • UsersTab.tsx - 完全迁移到新样式系统,移除了所有 dark: 前缀
    • MonitorTab.tsx - 完全迁移到新样式系统,移除了所有 dark: 前缀
  • ✅ 其他组件迁移(已完成):
    • TemplateManager.tsx - 完全迁移到新样式系统,移除了所有 dark: 前缀
    • page.tsx - 完全迁移到新样式系统,移除了所有 dark: 前缀
    • AppearanceSettingsPanel.tsx - 完全迁移到新样式系统,移除了所有 dark: 前缀

3. UI 样式统一化(历史)

  • ✅ 修复了 card-apple 类名,改为使用 cardStyles.base
  • ✅ 统一了边框颜色:border-gray-* → border-slate-*(与设计系统一致)
  • ✅ Admin 目录中的 text-gray-* / bg-gray-* / border-gray-* 类已全部替换为 slate 系列,浅色与深色模式的视觉基调保持一致

🔍 发现的问题和建议

1. 代码结构问题

问题:page.tsx 文件过大(3795 行)

影响:

  • 难以维护和调试
  • 代码复用性差
  • 性能可能受影响(组件过大)

建议:

  • ✅ 已创建 MonitorTab.tsx 组件
  • ✅ 已拆分 UsersTab.tsx(用户管理)
  • ✅ 已拆分 DepartmentsTab.tsx(架构管理)
  • ⏳ 继续拆分其他 Tab 组件:
    • ✅ CategoriesTab.tsx - 分类管理
    • ✅ InvitationsTab.tsx - 邀请管理
    • ✅ MaterialsTab.tsx - 素材管理
    • ✅ TemplateManager.tsx:已提取 Header / Built-in Grid / Custom Templates 等 UI 子组件,为后续拆出编辑器面板铺路
    • ✅ TemplateManager 编辑弹窗:基础信息、预设选择、JSON 高级配置抽象为 TemplateBasicsForm + TemplateAdvancedConfigPanel,编辑逻辑逐步下沉
    • ✅ TemplateManager 字段区、底部操作:TemplateFieldsEditor 承载字段配置 + 拖拽 UI,TemplateEditorFooter 统一处理提示与按钮状态
    • ✅ TemplateManager 预览面板:TemplatePreviewPanel 独立封装上传预览 UI 与 DnD 状态,主组件仅处理回调

问题:状态管理分散

当前状态:

  • 每个 Tab 的状态都在主组件中管理
  • 状态之间可能存在不必要的依赖

建议:

  • ✅ UsersTab / DepartmentsTab 已将本地 UI 状态与交互逻辑下沉到各自组件
  • 只保留共享状态在主组件(如 activeTab, toast)

4. UI 统一性问题

问题:部分地方仍使用旧的样式类

发现:

  • ✅ 基础文字/背景/边框色已统一为 slate 系列(含浅色与深色)
  • ✅ 深浅色样式已分离为两套独立配置,解决适配问题
  • ⏳ 部分按钮样式未使用 buttonStyles.*(建议逐步迁移到 useThemeStyles())
  • ⏳ 部分输入框仍未使用 inputStyles.*(建议逐步迁移到 useThemeStyles())

建议:

  • 全局搜索替换 gray- → slate-(在 admin 目录中)
  • ⏳ 确保所有按钮都使用 buttonStyles.*(InvitationsTab、CategoriesTab、MaterialsTab、UsersTab、DepartmentsTab ✅;其它 Tab 持续中)
  • ⏳ 确保所有输入框都使用 inputStyles.*(DepartmentsTab 重命名输入已调整)
  • ✅ 补充 buttonStyles.success 以覆盖绿色状态按钮场景
  • ✅ 新增 buttonModifiers(compact / compactXs / icon / block)辅助类,方便统一尺寸与布局
  • ✅ MaterialsTab 搜索操作、卡片操作按钮已统一到 buttonStyles + buttonModifiers,并将 <img> 替换为 next/image
  • ✅ UsersTab 搜索清空与用户操作按钮统一引用 buttonStyles + buttonModifiers
  • ✅ DepartmentsTab 搜索清空、操作按钮接入 buttonStyles + buttonModifiers; 新增 inputModifiers 并应用到重命名输入
  • ✅ TemplateManager 顶部搜索、预制/自定义模板动作按钮接入设计系统;新增 buttonModifiers.pill
  • ✅ TemplateManager 基础信息 / JSON 配置表单统一使用 inputStyles + inputModifiers,并抽离复用组件
  • ✅ TemplateManager 字段配置 / 底部操作按钮接入设计系统(字段编辑区统一控件样式,弹窗底部按钮使用 buttonStyles.secondary/primary + buttonModifiers.compact)
  • ✅ TemplateManager 预览面板 UI 与拖拽交互抽象为 TemplatePreviewPanel,复用设计系统控件
  • ✅ 清理 TemplatePreviewPanel 与 page.tsx 残留的 gray-* 渐变/分隔线/焦点样式,统一替换为 slate-* 调色
  • ✅ page.tsx 移除历史 Invitations UI、状态与数据请求,统一由 InvitationsTab 自主管理
  • ✅ page.tsx 移除重复的监控仪表板代码,统一使用 MonitorTab 组件

3. 逻辑优化建议

问题:数据获取逻辑重复

当前:

  • ✅ useDataFetch Hook 已抽离 loadUsersData / fetchDepartments / fetchTabData,主页面只关心状态驱动
  • ⏳ 更进一步的缓存(React Query / SWR)尚未落地

建议:

  • 后续可引入 React Query 或 SWR 进行跨 Tab 缓存与自动刷新
  • 或者在各 Tab 内使用独立数据源,减少主页面耦合

问题:权限检查分散

当前:

  • 权限检查在多个地方重复
  • canManageUser 等函数在主组件中定义

建议:

  • ✅ 已创建 usePermissions Hook,统一 canManageUser / 超管判定等权限逻辑
  • 后续可将其他权限相关逻辑继续提取到工具函数或 Hook 中

4. 性能优化建议

问题:大量 useMemo 和 useCallback

当前:

  • 主组件中有很多 useMemo 和 useCallback
  • 某些计算可能不需要缓存

建议:

  • ✅ 审查了每个 useMemo 和 useCallback 的必要性
    • departmentCollator - 使用 useMemo 合理(创建 Intl.Collator 对象)
    • userLookup - 使用 useMemo 合理(从数组创建 Map,避免重复计算)
    • fetchData, renameDepartment, createDepartment, deleteDepartment, findDepartmentManagers - 使用 useCallback 合理(作为 props 传递给子组件)
  • ✅ 创建了 _utils/api.ts 统一处理 API 错误,减少了重复的错误处理代码
  • ⏳ 将复杂的计算逻辑移到子组件中
  • ✅ 使用 React.memo 优化子组件渲染(UserTree 已实现)

问题:模态框状态管理

当前:

  • ✅ 分类/场景/平台新增、素材编辑相关模态已移交给各自 Tab 组件,page.tsx 清理全部遗留状态与 UI
  • ✅ 新增 useModalState Hook(app/admin/_hooks/useModalState.ts),统一管理用户编辑/转移最高权限模态的开合与状态,移除散落的 showPasswordModal、editingUser 布尔控制
  • ⏳ 用户信息编辑、转移最高权限 UI 仍托管在 page.tsx,可进一步下放到 UsersTab

建议:

  • 为剩余模态编写统一的模态管理 hook
  • 或者继续将模态迁移到对应的 Tab/组件内部

5. 代码质量建议

建议:添加错误边界

  • ✅ 新增 TabErrorBoundary 组件(app/admin/_components/TabErrorBoundary.tsx),并在 page.tsx 为各个 Tab 包裹,提供统一的 fallback + 重试
  • ⏳ 可进一步将 TabErrorBoundary 提炼到全局组件库,或为特定 Tab 定制更详细的错误提示

建议:添加加载状态统一管理

  • ✅ 创建统一的加载状态组件(LoadingState、ErrorState、EmptyState)
  • ✅ 统一错误提示样式,替换所有重复的加载/错误 UI
  • ✅ MonitorTab、MaterialsTab、page.tsx 已统一使用新的状态组件

建议:提取公共逻辑

  • ✅ 创建 hooks/useToast.ts 统一管理 Toast(page.tsx 已接入)
  • ✅ 创建 hooks/useDataFetch.ts 统一管理数据获取
  • ✅ 创建 _utils/api.ts 统一处理 API 错误响应和类型安全
    • parseErrorResponse() - 安全解析错误响应
    • parseSuccessResponse() - 安全解析成功响应
    • apiRequest() - 统一的 API 请求函数
    • getErrorMessage() - 获取错误消息的辅助函数
  • ✅ 提取表单验证逻辑到工具函数
    • 创建了 _utils/validators.ts 统一管理表单验证
    • validateNotEmpty() - 验证非空字符串
    • validateDepartmentName() - 验证部门名称
    • validateEmail() - 验证邮箱格式
    • validateFieldKey() - 验证字段键名(标识符规则)
    • validateUniqueKeys() - 验证字段键名唯一性
    • validateTemplateName() - 验证模板名称
    • validatePassword() - 验证密码
    • combineValidationResults() - 组合多个验证结果
    • page.tsx 和 TemplateManager.tsx 已使用新的验证函数
  • ✅ 创建格式化工具函数
    • 创建了 _utils/formatters.ts 统一管理格式化逻辑
    • formatDateTime() - 格式化日期时间(完整格式)
    • formatDate() - 格式化日期(仅日期部分)
    • formatTime() - 格式化时间(仅时间部分)
    • formatDateTimeShort() - 格式化日期时间(简短格式)
    • formatDateTimeLocale() - 使用本地化格式格式化日期时间
    • formatRelativeTime() - 格式化相对时间
    • formatFileSize() - 格式化文件大小
    • formatNumber() - 格式化数字(添加千位分隔符)
    • formatPercent() - 格式化百分比
    • MonitorTab.tsx、InvitationsTab.tsx、UserEditModal.tsx、TemplateManager.tsx 已使用新的格式化函数
  • ✅ 提取用户操作逻辑到 Hook
    • 创建了 _hooks/useUserOperations.ts 统一管理用户相关操作
    • updateUser() - 更新用户信息
    • deleteUser() - 删除用户
    • toggleDownload() - 切换下载权限
    • toggleActive() - 切换激活状态
    • setRole() - 设置用户角色
    • transferSuperAdmin() - 转移最高权限
    • page.tsx 已使用新的 Hook,代码更简洁
  • ✅ 提取部门操作逻辑到 Hook
    • 创建了 _hooks/useDepartmentOperations.ts 统一管理部门相关操作
    • createDepartment() - 创建部门
    • deleteDepartment() - 删除部门
    • renameDepartment() - 重命名部门
    • page.tsx 已使用新的 Hook,移除了重复的部门操作代码,代码更简洁
    • 创建了 _utils/validators.ts 统一管理表单验证
    • validateNotEmpty() - 验证非空字符串
    • validateDepartmentName() - 验证部门名称
    • validateEmail() - 验证邮箱格式
    • validateFieldKey() - 验证字段键名(标识符规则)
    • validateUniqueKeys() - 验证字段键名唯一性
    • validateTemplateName() - 验证模板名称
    • validatePassword() - 验证密码
    • combineValidationResults() - 组合多个验证结果
    • page.tsx 和 TemplateManager.tsx 已使用新的验证函数

6. 类型安全建议

问题:使用 any 类型

发现:

  • session?.user as any 多处使用
  • dashboardData 使用 any 类型

建议:

  • ✅ 定义完整的 Session 类型(SessionUser 接口)
  • ✅ 使用 DashboardData 类型替代 any(已在 types.ts 中定义)
  • ✅ 添加类型断言函数(getSessionUser)
  • ✅ 定义 API 响应类型(ApiErrorResponse, ApiSuccessResponse)
  • ✅ 移除 page.tsx 中所有 as any 使用
  • ✅ 更新 AppearanceSettingsPanel 使用 SessionUser 类型

7. 可访问性建议

建议:添加 ARIA 标签

  • ✅ 为 Tab 导航添加了完整的 ARIA 标签(role="tablist", role="tab", role="tabpanel")
  • ✅ 为所有 Tab 按钮添加了 aria-selected, aria-controls, id 属性
  • ✅ 为返回主页按钮和关闭 Toast 按钮添加了 aria-label
  • ✅ 为 Toast 通知添加了 role="status" 和 aria-live="polite"
  • ✅ 添加了键盘导航支持(Enter 和 Space 键)
  • ✅ 添加了焦点样式(focus:outline-none focus:ring-2)
  • ⏳ 继续为其他交互元素添加 ARIA 标签和键盘支持

8. 测试建议

建议:添加单元测试

  • 为工具函数添加测试
  • 为权限检查逻辑添加测试
  • 为数据转换逻辑添加测试

📋 下一步行动计划

注意:详细的优化计划和优先级已移至 优化计划与优先级.md,请参考该文档进行后续开发。

当前阶段:基础组件与UI统一

优先级 1:基础组件与UI统一(核心基础设施)

  1. ✅ 创建统一弹窗组件(components/ui/Modal.tsx)

    • ✅ 使用三层架构设计(基础层、颜色层、组合层)
    • ✅ 提供 useModal Hook(hooks/useModal.ts)
    • ✅ 支持多种尺寸(small, medium, large, xlarge, fullscreen)
    • ✅ 支持ESC键关闭、点击遮罩关闭
    • ✅ 完整的ARIA标签和键盘导航支持
    • ✅ 替换所有浏览器原生弹窗(confirm/alert/prompt)
    • ✅ 创建了 ConfirmDialog、AlertDialog、PromptDialog 组件
    • ✅ 创建了 DialogProvider 和 useDialog Hook
    • ✅ 替换了所有 admin 组件、首页、分享页面中的原生弹窗
  2. ✅ 素材预览面板统一

    • ✅ 创建了 MaterialPreviewModal 组件
    • ✅ 使用统一弹窗组件
    • ✅ 统一退出逻辑(ESC键、点击遮罩、关闭按钮)
    • ✅ 使用三层架构样式系统
  3. ✅ 首页素材展示响应式优化

    • ✅ 修复卡片比例固定问题(使用 aspect-[3/4] 替代固定高度 h-[400px])
    • ✅ 添加容器边距(px-4 sm:px-6 lg:px-8)避免卡片贴到浏览器边界
    • ✅ 使用三层架构样式系统(useThemeStyles() 和 cardStyles.base)
    • ✅ 优化图片 sizes 属性,提升响应式性能
    • ✅ 统一使用 slate 系列颜色,确保深浅色模式适配
  4. ✅ 首页UI统一到三层架构(主要部分)

    • ✅ 迁移了主要按钮样式(上传按钮、筛选按钮)
    • ✅ 迁移了搜索输入框样式
    • ✅ 迁移了筛选弹窗中的所有按钮样式
    • ✅ 迁移了筛选弹窗容器样式
    • ✅ 迁移了筛选弹窗关闭按钮样式
    • ⏳ 部分文本颜色和标签样式仍使用直接 Tailwind 类(可后续继续优化)

优先级 2:数据一致性与核心功能 5. ⏳ 用户信息修改后同步素材信息

  • 在 useUserOperations 中扩展
  1. ⏳ 模板管理整合到上传和分类
    • 严格检查模板管理面板逻辑
    • 将模板系统串起前后端

详细计划:请查看 优化计划与优先级.md

📝 代码规范建议

命名规范

  • 组件文件:PascalCase(如 UsersTab.tsx)
  • Hook 文件:camelCase with use prefix(如 usePermissions.ts)
  • 工具函数:camelCase(如 formatDate.ts)
  • 类型文件:types.ts 或 types/index.ts

文件组织

app/admin/
├── _components/
│   ├── types.ts              # 类型定义
│   ├── MonitorTab.tsx        # 监控仪表板
│   ├── UsersTab.tsx          # 用户管理
│   ├── DepartmentsTab.tsx    # 架构管理
│   ├── CategoriesTab.tsx     # 分类管理
│   ├── InvitationsTab.tsx    # 邀请管理
│   ├── MaterialsTab.tsx      # 素材管理
│   ├── TemplateManager.tsx   # 模板管理
│   └── AppearanceSettingsPanel.tsx
├── _hooks/                   # 自定义 hooks
│   ├── useToast.ts
│   ├── usePermissions.ts
│   └── useDataFetch.ts
├── _utils/                   # 工具函数
│   ├── validators.ts
│   └── formatters.ts
└── page.tsx                  # 主页面(简化后)

🎯 最终目标

  1. 代码可维护性:每个组件职责单一,易于理解和修改
  2. 代码复用性:公共逻辑提取到 hooks 和工具函数
  3. 类型安全:完整的 TypeScript 类型定义,减少运行时错误
  4. UI 一致性:统一使用设计系统,确保视觉一致性
  5. 性能优化:减少不必要的渲染,优化数据获取
  6. 用户体验:流畅的交互,清晰的错误提示