refactor: 代码架构重构 - 提取组件、统一状态管理和数据访问层
- 新增布局组件(SidebarBrand、SidebarUser、SidebarNavItem) - 新增通用UI组件(EmptyState、StatusBadge、TagInput、SearchBar) - 新增全局状态管理(UserContext) - 新增自定义Hooks(usePageState、useNavigation) - 新增统一数据访问层(src/services/api.js) - 新增常量配置(constants/pages.js、constants/storageKeys.js) - 样式文件模块化,拆分页面特定样式 - 更新README文档,添加组件和使用说明 - 同步OpenSpec规范到主specs目录
This commit is contained in:
49
openspec/specs/data-service-layer/spec.md
Normal file
49
openspec/specs/data-service-layer/spec.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Data Service Layer Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
提供统一的数据访问接口层,将数据访问逻辑与静态数据文件分离,便于后续对接真实 API。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: 统一数据访问接口
|
||||
系统 SHALL 提供 api 服务对象,包含按功能模块划分的数据访问方法,作为所有数据访问的统一入口。
|
||||
|
||||
#### Scenario: api.user 模块提供用户信息访问
|
||||
- **WHEN** 调用 api.user.getInfo()
|
||||
- **THEN** 系统返回用户信息对象(包含 name、avatar、role 等字段)
|
||||
|
||||
#### Scenario: api.skills 模块提供技能数据访问
|
||||
- **WHEN** 调用 api.skills.list()
|
||||
- **THEN** 系统返回所有技能列表数组
|
||||
|
||||
#### Scenario: api.skills 支持按 ID 查询单个技能
|
||||
- **WHEN** 调用 api.skills.getById(skillId)
|
||||
- **THEN** 系统返回对应 ID 的技能对象,若不存在则返回 undefined
|
||||
|
||||
#### Scenario: api.conversations 模块提供会话数据访问
|
||||
- **WHEN** 调用 api.conversations.list()
|
||||
- **THEN** 系统返回所有会话列表数组
|
||||
|
||||
#### Scenario: api.conversations 支持按场景获取聊天内容
|
||||
- **WHEN** 调用 api.conversations.getScene(sceneName)
|
||||
- **THEN** 系统返回对应场景的 HTML 内容字符串
|
||||
|
||||
#### Scenario: api.logs 模块支持筛选查询
|
||||
- **WHEN** 调用 api.logs.list(filters)
|
||||
- **THEN** 系统根据 filters 参数(用户、类型、状态)筛选并返回日志列表
|
||||
|
||||
### Requirement: 数据层与静态文件分离
|
||||
系统 SHALL 将数据访问逻辑与静态数据文件分离,便于后续对接真实 API。
|
||||
|
||||
#### Scenario: API 层内部调用静态数据文件
|
||||
- **WHEN** 调用 api 模块的任何方法
|
||||
- **THEN** 系统从对应的 data/*.js 文件读取并返回数据
|
||||
|
||||
#### Scenario: API 层支持数据转换
|
||||
- **WHEN** 静态数据结构与页面需求不一致
|
||||
- **THEN** 系统在 API 层进行数据转换,返回页面所需的格式
|
||||
|
||||
#### Scenario: API 层提供一致的返回格式
|
||||
- **WHEN** 调用 API 层方法
|
||||
- **THEN** 系统返回符合约定格式的数据(如对象、数组),无论底层存储格式如何
|
||||
52
openspec/specs/modular-styles/spec.md
Normal file
52
openspec/specs/modular-styles/spec.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Modular Styles Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
提供模块化的样式文件组织结构,将页面特定样式从全局样式文件中拆分到独立的页面样式文件中,提高代码的可维护性。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: 样式文件按页面拆分
|
||||
系统 SHALL 将页面特定样式从 global.scss 中拆分到独立的页面样式文件中,按功能组织。
|
||||
|
||||
#### Scenario: 工作台样式独立文件
|
||||
- **WHEN** 系统包含 _console.scss 文件
|
||||
- **THEN** 该文件包含工作台相关的所有样式(聊天、技能市场、日志查询、定时任务、项目管理等)
|
||||
|
||||
#### Scenario: 管理台样式独立文件
|
||||
- **WHEN** 系统包含 _admin.scss 文件
|
||||
- **THEN** 该文件包含管理台相关的所有样式(总览、部门管理、用户管理、项目管理等)
|
||||
|
||||
#### Scenario: 开发台样式独立文件
|
||||
- **WHEN** 系统包含 _developer.scss 文件
|
||||
- **THEN** 该文件包含开发台相关的所有样式(我的技能、技能编辑、开发文档等)
|
||||
|
||||
#### Scenario: 首页样式独立文件
|
||||
- **WHEN** 系统包含 _home.scss 文件
|
||||
- **THEN** 该文件包含首页相关的所有样式
|
||||
|
||||
### Requirement: global.scss 作为样式主入口
|
||||
系统 SHALL 保持 global.scss 作为样式主入口文件,导入所有样式模块。
|
||||
|
||||
#### Scenario: global.scss 导入设计系统模块
|
||||
- **WHEN** global.scss 文件被加载
|
||||
- **THEN** 系统按顺序导入 _variables.scss、_mixins.scss、_base.scss、_components.scss、_layout.scss
|
||||
|
||||
#### Scenario: global.scss 导入页面样式模块
|
||||
- **WHEN** global.scss 文件被加载
|
||||
- **THEN** 系统导入 pages/_console.scss、pages/_admin.scss、pages/_developer.scss、pages/_home.scss
|
||||
|
||||
#### Scenario: 通用样式保留在主文件中
|
||||
- **WHEN** 样式属于通用组件(按钮、表单、表格、状态标签等)
|
||||
- **THEN** 该样式保留在 _components.scss 或 _layout.scss 中,不移动到页面样式文件
|
||||
|
||||
### Requirement: 页面样式文件组织结构
|
||||
系统 SHALL 在 src/styles/pages/ 目录下按页面组织样式文件,每个文件包含对应页面的所有特定样式。
|
||||
|
||||
#### Scenario: 页面样式文件命名规范
|
||||
- **WHEN** 创建页面样式文件
|
||||
- **THEN** 文件名使用 _<page-name>.scss 格式(如 _console.scss、_admin.scss)
|
||||
|
||||
#### Scenario: 页面样式文件内容结构
|
||||
- **WHEN** 查看页面样式文件
|
||||
- **THEN** 该文件包含页面特定的布局、组件、状态等样式,使用清晰的注释分节
|
||||
41
openspec/specs/reusable-components/spec.md
Normal file
41
openspec/specs/reusable-components/spec.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Reusable Components Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
提供可复用的布局组件和通用 UI 组件库,用于在不同页面中保持一致的视觉呈现和交互体验。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: 布局组件复用
|
||||
系统 SHALL 提供可复用的布局组件,包括品牌区域、用户信息区域、导航项组件,用于在不同页面中保持一致的视觉呈现。
|
||||
|
||||
#### Scenario: SidebarBrand 组件渲染
|
||||
- **WHEN** 页面使用 SidebarBrand 组件并传入 subtitle 属性
|
||||
- **THEN** 系统显示 GrandClaw 品牌 logo 和对应的副标题文本
|
||||
|
||||
#### Scenario: SidebarUser 组件显示用户信息
|
||||
- **WHEN** 页面使用 SidebarUser 组件
|
||||
- **THEN** 系统从 UserContext 获取用户信息并显示用户头像、姓名和角色
|
||||
|
||||
#### Scenario: SidebarNavItem 组件支持状态切换
|
||||
- **WHEN** 页面使用 SidebarNavItem 组件并传入 active 状态
|
||||
- **THEN** 系统根据 active 状态应用相应的激活样式
|
||||
|
||||
### Requirement: 通用 UI 组件库
|
||||
系统 SHALL 提供通用 UI 组件库,包括空状态组件、状态标签组件、标签输入组件、搜索栏组件,支持在多个页面中复用。
|
||||
|
||||
#### Scenario: EmptyState 组件显示空状态
|
||||
- **WHEN** 页面使用 EmptyState 组件并传入 icon、message、description 属性
|
||||
- **THEN** 系统显示居中的空状态提示,包含图标、标题和描述文本
|
||||
|
||||
#### Scenario: StatusBadge 组件显示不同状态
|
||||
- **WHEN** 页面使用 StatusBadge 组件并传入 status 属性(如 running、stopped、warning、error)
|
||||
- **THEN** 系统根据 status 值应用对应的颜色样式和图标
|
||||
|
||||
#### Scenario: TagInput 组件支持标签增删
|
||||
- **WHEN** 用户在 TagInput 组件中输入文本并按回车
|
||||
- **THEN** 系统将输入内容添加为标签,并显示删除按钮
|
||||
|
||||
#### Scenario: SearchBar 组件提供筛选功能
|
||||
- **WHEN** 页面使用 SearchBar 组件并传入搜索条件配置
|
||||
- **THEN** 系统渲染对应的筛选输入框,并在用户输入时触发 onChange 回调
|
||||
52
openspec/specs/unified-state-management/spec.md
Normal file
52
openspec/specs/unified-state-management/spec.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Unified State Management Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
提供统一的状态管理方案,包括全局用户信息上下文、页面状态持久化、导航逻辑管理,确保应用状态的一致性和可维护性。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: 用户信息全局上下文
|
||||
系统 SHALL 使用 React Context API 提供全局用户信息上下文,确保用户数据在整个应用中保持一致。
|
||||
|
||||
#### Scenario: UserContext 提供用户信息
|
||||
- **WHEN** 组件使用 useUserContext Hook
|
||||
- **THEN** 系统返回包含用户 name、avatar、role 的用户信息对象
|
||||
|
||||
#### Scenario: 用户信息在多个页面同步显示
|
||||
- **WHEN** 用户信息在 UserContext 中更新
|
||||
- **THEN** 所有使用 UserContext 的组件自动更新显示
|
||||
|
||||
#### Scenario: UserContext 提供默认值
|
||||
- **WHEN** 应用启动且没有提供用户信息
|
||||
- **THEN** 系统使用默认用户信息(name: '张三', avatar: '张', role: 'AI 产品部')
|
||||
|
||||
### Requirement: 页面状态持久化 Hook
|
||||
系统 SHALL 提供 usePageState Hook,封装页面状态持久化逻辑,自动处理 localStorage 同步和主页跳转重置。
|
||||
|
||||
#### Scenario: usePageState 初始化从 localStorage 恢复状态
|
||||
- **WHEN** 页面使用 usePageState Hook 并传入 storageKey 和 defaultPage
|
||||
- **THEN** 系统从 localStorage 读取之前保存的页面状态,若无则使用 defaultPage
|
||||
|
||||
#### Scenario: usePageState 自动同步状态到 localStorage
|
||||
- **WHEN** 调用 usePageState 返回的 setCurrentPage 函数
|
||||
- **THEN** 系统更新状态并自动保存到 localStorage
|
||||
|
||||
#### Scenario: usePageState 处理主页跳转重置
|
||||
- **WHEN** 从主页跳转到页面(location.state.fromHome 为 true)
|
||||
- **THEN** 系统重置页面状态为默认值,并清除路由 state
|
||||
|
||||
#### Scenario: usePageState 提供 getPageTitle 函数
|
||||
- **WHEN** 调用 usePageState 返回的 getPageTitle 函数
|
||||
- **THEN** 系统根据当前页面 ID 从配置中查找并返回对应的页面标题
|
||||
|
||||
### Requirement: 导航逻辑 Hook
|
||||
系统 SHALL 提供 useNavigation Hook,统一处理页面导航和路由状态管理。
|
||||
|
||||
#### Scenario: useNavigation 提供页面切换函数
|
||||
- **WHEN** 调用 useNavigation 返回的 navigateToPage 函数并传入目标页面 ID
|
||||
- **THEN** 系统更新当前页面状态并执行相应导航逻辑
|
||||
|
||||
#### Scenario: useNavigation 处理带数据的页面切换
|
||||
- **WHEN** 调用 navigateToPage 并传入目标页面 ID 和附加数据(如 skillId)
|
||||
- **THEN** 系统更新页面状态和附加数据状态
|
||||
Reference in New Issue
Block a user