11 KiB
Raw Blame History

设计文档 - UI修复和功能还原

概述

本设计文档描述了由壹点3D素材平台UI修复和功能还原的技术实现方案。系统需要修复当前版本中存在的UI问题和功能缺失,包括筛选条件显示、榜单面板交互、页面滚动管理、头部菜单导航、网络诊断工具、素材卡片样式和素材详情页面一致性等方面。

架构

整体架构

系统采用Next.js 13+ App Router架构,使用React Server Components和Client Components混合模式。UI修复主要涉及以下层次:

  1. 页面层 (app/page.tsx): 首页主逻辑,包含筛选状态管理和素材展示
  2. 组件层 (components/): 可复用的UI组件,如Header、RankingPanel、NetworkDiagnoseModal等
  3. 状态管理层: 使用React Hooks进行本地状态管理,使用localStorage/sessionStorage进行持久化
  4. 样式层: 使用Tailwind CSS进行样式管理

关键设计决策

  1. 筛选条件显示: Material_Type不应出现在"当前筛选"区域,因为它是页面的主要分类维度,不是筛选条件
  2. 状态持久化: 使用localStorage保存用户偏好(如榜单面板状态和位置),使用sessionStorage保存临时状态(如滚动位置)
  3. 拖拽实现: 使用原生DOM事件实现拖拽,避免引入额外的库
  4. 滚动管理: 移除强制滚动位置恢复逻辑,允许浏览器自然处理滚动

组件和接口

1. 首页筛选组件 (app/page.tsx)

状态接口

interface FilterState {
  searchKeyword: string
  selectedCategory: string
  selectedScene: string
  selectedMaterialType: string  // 不显示在"当前筛选"中
  selectedPlatform: string
  selectedProductCategory: string
  selectedMonth: string
}

关键函数

  • renderActiveFilters(): 渲染"当前筛选"区域,排除Material_Type
  • clearFilter(filterName: string): 清除单个筛选条件
  • clearAllFilters(): 清除所有筛选条件

2. 榜单面板组件 (components/RankingPanel.tsx)

状态接口

interface RankingPanelState {
  isVisible: boolean
  position: { x: number; y: number }
  isDragging: boolean
}

关键函数

  • handleDragStart(e: MouseEvent): 开始拖拽
  • handleDrag(e: MouseEvent): 拖拽中
  • handleDragEnd(e: MouseEvent): 结束拖拽
  • constrainPosition(pos: {x, y}): 限制位置在视口内
  • saveState(): 保存状态到localStorage
  • restoreState(): 从localStorage恢复状态
  • toggleVisibility(): 切换可见性

迷你按钮组件

interface MiniButtonProps {
  onClick: () => void
  position: { x: number; y: number }
}

3. 头部菜单组件 (components/Header.tsx)

菜单项接口

interface MenuItem {
  label: string
  icon: ReactNode
  onClick: () => void
  visible: boolean  // 基于权限控制
}

关键函数

  • handleProfileClick(): 导航到个人中心
  • handleUpdateLogClick(): 显示更新记录弹窗
  • handleSystemSettingsClick(): 导航到系统设置(仅管理员)
  • handleNetworkDiagnoseClick(): 显示网络诊断弹窗

4. 网络诊断组件 (components/NetworkDiagnoseModal.tsx)

诊断结果接口

interface DiagnosticResult {
  timestamp: string
  downloadSpeed: number  // MB/s
  uploadSpeed: number    // MB/s
  storageConnectivity: boolean
  storageLatency: number // ms
  networkType: 'intranet' | 'internet'
}

关键函数

  • runDiagnostic(): 执行完整诊断
  • testDownloadSpeed(): 测试下载速度
  • testUploadSpeed(): 测试上传速度
  • testStorageConnectivity(): 测试存储连通性
  • cancelDiagnostic(): 取消诊断
  • copyResult(): 复制诊断结果

5. 素材卡片组件

样式接口

interface MaterialCardStyle {
  buttonHeight: string
  buttonAlignment: 'vertical' | 'horizontal'
  hoverEffect: boolean
}

数据模型

LocalStorage数据结构

// 榜单面板状态
interface RankingPanelStorage {
  isVisible: boolean
  position: { x: number; y: number }
}

// 键名: 'ranking_panel_state'

SessionStorage数据结构

// 首页滚动位置和状态缓存
interface HomePageCache {
  scrollPosition: number
  materials: Material[]
  filters: FilterState
  timestamp: number
}

// 键名: 'home_scroll_position', 'home_materials_cache'

正确性属性

属性是一个特征或行为,应该在系统的所有有效执行中保持为真——本质上是关于系统应该做什么的形式化陈述。属性作为人类可读规范和机器可验证正确性保证之间的桥梁。

属性 1: Material_Type排除规则

对于任何筛选状态,当Material_Type被选中时,"当前筛选"区域不应该显示Material_Type标签

验证: 需求 1.2

属性 2: 筛选条件显示完整性

对于任何非Material_Type的筛选条件,当该筛选条件被激活时,"当前筛选"区域应该显示该筛选条件

验证: 需求 1.1

属性 3: 筛选条件清除即时性

对于任何筛选条件,当用户清除该筛选条件时,该筛选条件应该立即从"当前筛选"区域移除

验证: 需求 1.3

属性 4: 空筛选隐藏规则

对于任何页面状态,当没有任何筛选条件激活时,"当前筛选"区域不应该显示

验证: 需求 1.4

属性 5: 品类筛选持久性

对于任何品类筛选,在执行任何其他操作(页面状态更新、页面内导航、添加其他筛选)后,品类筛选应该保持不变,直到被明确清除

验证: 需求 2.1, 2.2, 2.3, 2.4

属性 6: 榜单面板和迷你按钮互斥性

对于任何榜单面板状态,榜单面板可见时迷你按钮应该隐藏,榜单面板隐藏时迷你按钮应该可见

验证: 需求 3.1, 3.3

属性 7: 榜单面板状态往返

对于任何榜单面板状态,保存到localStorage然后恢复应该产生相同的状态

验证: 需求 3.4, 3.5

属性 8: 迷你按钮打开面板

对于任何隐藏的榜单面板,点击迷你按钮应该打开榜单面板

验证: 需求 3.2

属性 9: 拖拽跟随光标

对于任何拖拽操作,榜单面板的位置应该跟随鼠标光标移动

验证: 需求 4.1

属性 10: 拖拽结束固定位置

对于任何拖拽操作,释放鼠标后榜单面板应该固定在新位置

验证: 需求 4.2

属性 11: 榜单面板位置往返

对于任何榜单面板位置,保存到localStorage然后恢复应该产生相同的位置

验证: 需求 4.3, 4.4

属性 12: 拖拽边界约束

对于任何拖拽操作,当面板被拖到视口外时,面板位置应该被约束在视口边界内

验证: 需求 4.5

属性 13: 滚动自由性

对于任何页面状态(包括刷新后),用户应该能够自由滚动页面,不受任何锁定或干扰

验证: 需求 5.1, 5.2, 5.3

属性 14: 滚动恢复性能

对于任何滚动位置恢复操作,恢复应该在100ms内完成

验证: 需求 5.4

属性 15: 系统设置菜单权限控制

对于任何用户,当用户不是管理员时,系统设置菜单项不应该显示

验证: 需求 6.4

属性 16: 网络诊断选项完整性

对于任何网络诊断弹窗,弹窗应该显示所有诊断选项(下载速度、上传速度、存储连通性)

验证: 需求 7.2

属性 17: 网络诊断结果完整性

对于任何成功的诊断测试,结果应该包含连接状态和延迟信息

验证: 需求 7.4

属性 18: 网络诊断错误处理

对于任何失败的诊断测试,系统应该显示错误信息和故障排除建议

验证: 需求 7.5

属性 19: 素材卡片按钮布局一致性

对于任何素材卡片,编辑、分享和下载按钮应该有正确的高度、垂直对齐,并在卡片大小改变时保持比例

验证: 需求 8.1, 8.3, 8.4

属性 20: 素材卡片hover效果

对于任何素材卡片,鼠标悬停时应该高亮操作按钮

验证: 需求 8.2

属性 21: 素材详情页面一致性

对于任何素材类型,详情页面应该有一致的布局、样式、UI模式、字体和间距

验证: 需求 9.1, 9.2, 9.3, 9.4

错误处理

1. 筛选条件错误

  • 场景: 筛选条件状态不一致
  • 处理: 重置所有筛选条件到默认状态
  • 用户反馈: 显示提示信息"筛选条件已重置"

2. LocalStorage错误

  • 场景: LocalStorage读写失败或数据损坏
  • 处理: 使用默认值,清除损坏的数据
  • 用户反馈: 静默处理,不影响用户体验

3. 拖拽错误

  • 场景: 拖拽过程中发生异常
  • 处理: 重置面板到默认位置
  • 用户反馈: 无需提示,面板回到默认位置

4. 网络诊断错误

  • 场景: 诊断测试失败或超时
  • 处理: 显示错误信息和建议
  • 用户反馈: 显示详细的错误信息和故障排除步骤

5. 导航错误

  • 场景: 路由导航失败
  • 处理: 显示错误提示,保持在当前页面
  • 用户反馈: 显示Toast提示"导航失败,请重试"

测试策略

单元测试

单元测试用于验证特定示例、边缘情况和错误条件:

  1. 筛选条件显示测试

    • 测试Material_Type不出现在"当前筛选"中
    • 测试其他筛选条件正确显示
    • 测试清除筛选条件的功能
  2. 榜单面板测试

    • 测试面板显示/隐藏切换
    • 测试迷你按钮显示/隐藏
    • 测试localStorage保存和恢复
  3. 拖拽功能测试

    • 测试拖拽事件处理
    • 测试边界约束逻辑
    • 测试位置保存
  4. 头部菜单测试

    • 测试菜单项点击事件
    • 测试权限控制逻辑
    • 测试弹窗显示
  5. 网络诊断测试

    • 测试诊断流程
    • 测试结果显示
    • 测试错误处理

属性测试

属性测试用于验证通用属性在所有输入下都成立:

  1. 筛选条件属性测试

    • 属性1-5: 测试筛选条件的显示、清除和持久性
    • 最少100次迭代,使用随机筛选条件组合
  2. 榜单面板属性测试

    • 属性6-12: 测试面板状态、拖拽和位置管理
    • 最少100次迭代,使用随机位置和状态
  3. 滚动管理属性测试

    • 属性13-14: 测试滚动自由性和性能
    • 最少100次迭代,使用随机滚动位置
  4. UI一致性属性测试

    • 属性15-21: 测试UI组件的一致性和正确性
    • 最少100次迭代,使用随机素材数据

测试框架

  • 单元测试: Jest + React Testing Library
  • 属性测试: fast-check (JavaScript/TypeScript的属性测试库)
  • E2E测试: Playwright (用于完整的用户流程测试)

测试标签格式

每个属性测试必须使用以下格式标记:

// Feature: ui-fixes, Property 1: Material_Type排除规则
test.prop([fc.record({...})])('Material_Type should not appear in active filters', ...)