# GrandClaw 原型项目
## 项目概述
GrandClaw 是一个企业级AI智能助手平台的前端原型项目,主要用于展示平台的主要页面布局、交互流程和视觉设计。项目采用现代化的前端技术栈,实现了四大核心模块:
- **首页**:平台入口,包含登录功能
- **工作台**:用户与AI助手交互的主要界面,包含聊天、技能市场、日志查询、定时任务等功能
- **管理台**:运营管理界面,包含总览、部门管理、用户管理、项目管理
- **开发台**:技能开发界面,包含我的技能、技能编辑、开发文档等
## 技术栈
### 核心框架
- **React 19.2.4**:UI组件库
- **React Router 7.13.1**:路由管理(使用HashRouter)
- **Vite 8.0.1**:构建工具和开发服务器
### UI与样式
- **react-icons 5.5.0**:图标库(Feather + FontAwesome图标集)
- **Sass 1.98.0**:CSS预处理器
- **SCSS模块化**:变量、混入、组件、布局、页面分离
### 构建优化
- **vite-plugin-singlefile 2.3.2**:单文件打包,解决CORS问题
- **相对路径配置**:支持直接打开HTML文件运行
- **注意**:构建时会显示弃用警告 `WARN inlineDynamicImports option is deprecated, please use codeSplitting: false instead.`,这是由 `vite-plugin-singlefile` 插件内部使用弃用选项导致的,不影响功能,可以忽略。
### 包管理
- **pnpm**:高效的包管理器
## 项目结构
```
grandclaw-archtype/
├── dist/ # 构建输出目录(单个index.html)
├── public/ # 静态资源
├── src/ # 源代码
│ ├── App.jsx # 主路由配置
│ ├── main.jsx # 应用入口
│ ├── components/ # 组件
│ │ ├── layout/ # 布局组件(SidebarBrand、SidebarUser、SidebarNavItem)
│ │ ├── common/ # 通用UI组件(EmptyState、StatusBadge、TagInput、SearchBar)
│ │ ├── Layout.jsx # 通用布局组件(侧边栏+主内容)
│ │ └── ListSelector.jsx # 列表选择器组件(支持单选/多选)
│ ├── contexts/ # 全局状态管理
│ │ └── UserContext.jsx # 用户信息上下文
│ ├── hooks/ # 自定义Hook
│ │ ├── useLocalStorage.js # localStorage状态管理Hook
│ │ ├── usePageState.js # 页面状态持久化Hook
│ │ └── useNavigation.js # 导航逻辑Hook
│ ├── constants/ # 常量定义
│ │ ├── pages.js # 页面配置(路由、标题、图标)
│ │ └── storageKeys.js # localStorage键名常量
│ ├── services/ # 数据访问层
│ │ └── api.js # 统一数据访问接口
│ ├── data/ # 模拟数据
│ │ ├── conversations.js # 聊天场景数据
│ │ ├── developerData.js # 开发台数据
│ │ ├── logs.js # 日志数据
│ │ ├── members.js # 成员数据
│ │ ├── skills.js # 技能数据
│ │ ├── tasks.js # 定时任务数据
│ │ └── adminData.js # 管理台数据(部门/用户/项目/总览/日志)
│ ├── pages/ # 页面组件
│ │ ├── HomePage.jsx # 首页
│ │ ├── LoginPage.jsx # 登录页面
│ │ ├── ConsolePage.jsx # 工作台主页面
│ │ ├── AdminPage.jsx # 管理台主页面
│ │ ├── DeveloperPage.jsx # 开发台主页面
│ │ ├── console/ # 工作台子页面
│ │ │ ├── ChatPage.jsx # 聊天页面
│ │ │ ├── SkillsPage.jsx # 技能市场
│ │ │ ├── SkillDetailPage.jsx # 技能详情
│ │ │ ├── LogsPage.jsx # 日志查询
│ │ │ ├── TasksPage.jsx # 定时任务
│ │ │ ├── TaskDetailPage.jsx # 任务详情
│ │ │ ├── AccountPage.jsx # 账号管理
│ │ │ ├── ProjectsPage.jsx # 项目管理
│ │ │ ├── MemberConfigPage.jsx # 成员配置
│ │ │ └── AddMemberPage.jsx # 增加成员
│ │ ├── admin/ # 管理台子页面
│ │ │ ├── OverviewPage.jsx # 运营总览
│ │ │ ├── DepartmentsPage.jsx # 部门管理
│ │ │ ├── AddDepartmentPage.jsx # 新增/编辑部门
│ │ │ ├── UsersPage.jsx # 用户管理
│ │ │ ├── AddUserPage.jsx # 新增/编辑用户
│ │ │ ├── AdminProjectsPage.jsx # 项目管理
│ │ │ ├── AddProjectPage.jsx # 新增/编辑项目
│ │ │ └── AdminLogsPage.jsx # 全局日志查询
│ │ └── developer/ # 开发台子页面
│ │ ├── MySkillsPage.jsx # 我的技能
│ │ ├── UploadSkillPage.jsx # 创建技能
│ │ ├── NewVersionPage.jsx # 上传新版本
│ │ ├── DevDocsPage.jsx # 开发文档
│ │ ├── DevAccountPage.jsx # 开发者设置
│ │ └── SkillEditorPage.jsx # 技能详情/编辑
│ └── styles/ # SCSS样式模块
│ ├── _variables.scss # 设计系统变量
│ ├── _mixins.scss # 可复用混入
│ ├── _base.scss # 基础重置和全局样式
│ ├── _components.scss # 通用组件样式
│ ├── _layout.scss # 布局相关样式
│ ├── _pages.scss # 页面特定样式
│ └── global.scss # 主样式文件,导入所有模块
├── index.html # HTML入口文件
├── package.json # 项目配置和依赖
├── vite.config.js # Vite配置
└── pnpm-lock.yaml # 依赖锁定文件
```
## 开发指南
### 环境要求
- Node.js 18+
- pnpm(推荐)或 npm
### 安装依赖
```bash
pnpm install
```
### 开发模式
```bash
pnpm dev
# 访问 http://localhost:5173
```
### 构建生产版本
```bash
pnpm build
# 生成 dist/index.html(单个HTML文件)
```
### 预览生产构建
直接双击 `dist/index.html` 文件,或在浏览器中打开。
## 核心功能
### 1. 首页
- 平台品牌展示
- 导航入口(工作台、开发台、管理台)
- 登录入口
### 2. 登录页面
- 用户名/邮箱登录
- 密码输入
- 验证码(防爆破)
- 记住我功能
- 忘记密码链接
### 3. 工作台(Console)
- **聊天界面**:支持多种聊天场景(欢迎页、普通对话、技能调用、文件上传)
- **技能市场**:浏览、订阅、查看技能详情
- **日志查询**:支持按用户、类型、状态筛选
- **定时任务**:管理定时任务,支持启用/禁用,查看任务详情
- **项目管理**:成员列表,增加成员
- **账号管理**:个人信息和密码修改
### 4. 管理台(Admin)
- **运营总览**:平台运营指标卡片(用户总数、部门数量、项目数量、今日调用)、异常/待办事项提醒、最近操作日志
- **部门管理**:部门列表,支持搜索筛选、新增、编辑、启用/禁用、删除确认
- **用户管理**:用户列表,支持搜索筛选(关键词/部门/状态)、新增、编辑、启用/禁用、删除确认,角色区分(管理员/开发者/成员)
- **项目管理**:项目列表,支持搜索筛选、新增、编辑、启用/禁用、删除确认
- **日志查询**:全局系统日志查询,支持多维度筛选(关键词、用户、部门、类型、状态、时间范围)
### 5. 开发台(Developer)
- **我的技能**:已开发的技能列表
- **创建技能**:上传新技能
- **上传新版本**:为已发布的技能上传新版本
- **技能编辑**:编辑技能配置、版本管理
- **开发文档**:技能开发相关文档
- **开发者设置**:开发者账号信息
## 路由结构
项目使用 **HashRouter**,所有路由基于哈希路径,支持直接打开HTML文件运行。
### 主要路由
```
/ # 首页
/login # 登录页面
/console # 工作台
/admin # 管理台
/developer # 开发台
```
### 路由配置(App.jsx)
```jsx
import { HashRouter as Router, Routes, Route } from 'react-router-dom';
} />
} />
} />
} />
} />
```
## 通用组件
### 布局组件
#### SidebarBrand 品牌区域
侧边栏顶部的品牌展示组件。
```jsx
import { SidebarBrand } from '../components/layout/SidebarBrand.jsx';
```
#### SidebarUser 用户信息
侧边栏底部的用户信息展示组件,使用全局用户上下文。
```jsx
import { SidebarUser } from '../components/layout/SidebarUser.jsx';
navigate('/account')}
wrapperClassName="sidebar-user"
infoClassName="sidebar-user-info"
nameClassName="sidebar-user-name"
roleClassName="sidebar-user-role"
/>
```
#### SidebarNavItem 导航项
侧边栏导航菜单项组件。
```jsx
import { SidebarNavItem } from '../components/layout/SidebarNavItem.jsx';
}
label="智能助手"
active={currentPage === 'chat'}
onClick={() => setCurrentPage('chat')}
itemClassName="sidebar-nav-item"
iconClassName="sidebar-nav-icon"
textClassName="sidebar-nav-text"
/>
```
### 通用UI组件
#### EmptyState 空状态
用于展示空列表或无数据状态的组件。
```jsx
import EmptyState from '../components/common/EmptyState.jsx';
}
title="暂无数据"
description="当前没有可显示的内容"
/>
```
#### Modal 弹窗
用于展示确认操作的弹窗组件,支持自定义标题和内容。
```jsx
import Modal from '../components/common/Modal.jsx';
确定要删除这个任务吗?
```
#### Toast 消息提示
用于展示操作结果的消息提示组件,支持成功、错误、警告、信息四种类型。
```jsx
import Toast from '../components/common/Toast.jsx';
setShowToast(false)}
/>
```
**支持的类型:**
- `success` - 成功(绿色)
- `error` - 错误(红色)
- `warning` - 警告(黄色)
- `info` - 信息(蓝色)
#### StatusBadge 状态标签
用于显示状态(成功、失败、警告等)的标签组件。
```jsx
import StatusBadge from '../components/common/StatusBadge.jsx';
```
#### TagInput 标签输入
支持输入标签的输入框组件。
```jsx
import TagInput from '../components/common/TagInput.jsx';
```
#### SearchBar 搜索框
通用的搜索输入框组件。
```jsx
import SearchBar from '../components/common/SearchBar.jsx';
```
### 列表组件
#### ListSelector 列表选择器
通用的列表选择器组件,支持单选和多选模式。
```jsx
import ListSelector from '../components/ListSelector.jsx';
{}} // 清除已选回调
/>
```
## 状态管理
### 全局状态
#### UserContext 用户信息上下文
全局用户信息状态,通过 `UserProvider` 提供给整个应用。
```jsx
import { UserProvider, useUserContext } from '../contexts/UserContext.jsx';
// 在 App.jsx 中包裹
// 在组件中使用
function Component() {
const { user } = useUserContext();
return {user.name}
;
}
```
### 自定义 Hooks
#### usePageState 页面状态持久化
处理页面切换状态的 Hook,支持 localStorage 持久化和主页跳转重置。
```javascript
import { usePageState } from '../hooks/usePageState.js';
import { CONSOLE_PAGES } from '../constants/pages.js';
import { CONSOLE_KEYS } from '../constants/storageKeys.js';
const { currentPage, setCurrentPage } = usePageState({
storageKey: CONSOLE_KEYS.CURRENT_PAGE,
defaultPage: 'chat',
pageTitles: CONSOLE_PAGES,
});
```
#### useNavigation 导航逻辑
封装页面导航逻辑的 Hook,支持携带额外数据。
```javascript
import { useNavigation } from '../hooks/useNavigation.js';
const { navigateToPage, extraData } = useNavigation(setCurrentPage);
// 导航到指定页面
navigateToPage('skills', { skillId: '1' });
// 获取导航传递的数据
const skillId = extraData.skillId;
```
#### useLocalStorage localStorage 状态管理
同步组件状态到 localStorage 的 Hook。
```javascript
import { useLocalStorage } from '../hooks/useLocalStorage.js';
const [value, setValue] = useLocalStorage('myKey', 'defaultValue');
setValue('newValue'); // 自动同步到 localStorage
```
### 导航状态持久化策略
每个主要页面(工作台、管理台、开发台)都有独立的`localStorage`键:
```javascript
// 工作台
localStorage.setItem('console_currentPage', 'chat');
localStorage.setItem('console_currentScene', 'welcome');
// 管理台
localStorage.setItem('admin_currentPage', 'overview');
// 开发台
localStorage.setItem('developer_currentPage', 'mySkills');
localStorage.setItem('developer_currentSkillId', '1');
```
### 主页跳转 vs 刷新浏览器
通过`location.state.fromHome`区分两种导航来源:
```javascript
// 从主页跳转:显示默认页面
useEffect(() => {
if (location.state?.fromHome) {
setCurrentPage('chat'); // 默认页面
navigate('.', { replace: true, state: {} }); // 清除state
}
}, [location.state]);
// 刷新浏览器:从localStorage恢复
const [currentPage, setCurrentPage] = useState(() => {
return localStorage.getItem('console_currentPage') || 'chat';
});
```
## 样式系统
### SCSS模块化结构
```
src/styles/
├── _variables.scss # 设计系统变量(颜色、间距、阴影等)
├── _mixins.scss # 可复用混入(媒体查询、弹性布局等)
├── _base.scss # 基础重置、CSS变量定义、body样式
├── _components.scss # 通用组件(按钮、卡片、表单、状态标签)
├── _layout.scss # 布局相关(侧边栏、主内容区)
├── _pages.scss # 页面特定样式(首页、管理台等)
└── global.scss # 主文件,导入所有模块
```
### 设计系统变量(_variables.scss)
```scss
// 品牌主色
$primary: #3B82F6;
$primary-light: #EFF6FF;
$primary-dark: #2563EB;
// 功能色
$success: #10B981;
$warning: #F59E0B;
$danger: #EF4444;
// 中性色
$text-1: #1E293B;
$text-2: #475569;
$text-3: #94A3B8;
// 布局尺寸
$sidebar-width: 240px;
$header-height: 60px;
$radius-md: 8px;
```
### 状态标签样式
支持多种状态标签:
- `status-running` - 成功/运行中(绿色)
- `status-stopped` - 停止/禁用(灰色)
- `status-warning` - 警告(黄色)
- `status-error` - 失败/错误(红色)
### 角色标签样式
- `role-admin` - 管理员(蓝色)
- `role-member` - 成员(灰色)
- `role-developer` - 开发者(橙色)
## 数据访问层
项目使用统一的数据访问接口 `src/services/api.js`,所有数据获取都通过 API 层进行,便于未来对接后端服务。
### API 使用示例
```javascript
import { api } from '../services/api.js';
// 获取技能列表
const skills = api.skills.list();
// 获取单个技能详情
const skill = api.skills.getById('1');
// 获取日志列表
const logs = api.logs.list();
// 按条件筛选日志
const filteredLogs = api.logs.filter({ user, type, status });
// 获取开发者技能
const mySkills = api.developer.getMySkills();
// 获取成员列表
const members = api.members.list();
```
### API 模块结构
- `api.user` - 用户信息
- `api.skills` - 技能市场(列表、详情、文件、版本、图标)
- `api.conversations` - 聊天场景和对话历史
- `api.logs` - 操作日志(列表、筛选)
- `api.developer` - 开发台数据(技能、分类、模型、文档)
- `api.members` - 项目成员
- `api.tasks` - 定时任务
- `api.admin` - 管理台(总览、部门、用户、项目、全局日志)
## 数据模拟
所有数据都存储在 `src/data/` 目录下的JavaScript文件中,作为静态模拟数据。API 服务层统一从这些文件读取数据。
### 数据文件说明
- `conversations.js`:聊天场景和对话历史
- `skills.js`:技能市场数据,包含技能详情、文件列表、版本历史
- `developerData.js`:开发台数据,包含我的技能、技能分类、开发文档
- `logs.js`:操作日志数据(成功/失败/警告状态)
- `tasks.js`:定时任务数据(包含任务配置和执行日志)
- `adminData.js`:管理台数据(部门列表、用户列表、项目列表、总览指标、全局日志、可选项数据)
- `members.js`:项目成员数据
## 构建和部署
### 构建配置(vite.config.js)
```javascript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { viteSingleFile } from 'vite-plugin-singlefile';
export default defineConfig({
base: './', // 相对路径,支持直接打开HTML文件
plugins: [
react(),
viteSingleFile() // 单文件打包
],
});
```
### 构建产物
运行 `pnpm build` 后生成:
- `dist/index.html`:包含所有JavaScript和CSS的单个HTML文件
- 支持直接双击打开,无需服务器
- 使用HashRouter,路由正常工作
### 部署方式
1. **本地运行**:直接双击 `dist/index.html`
2. **静态服务器**:将 `dist/` 目录部署到任何静态文件服务器
3. **CDN部署**:上传单个HTML文件到CDN即可
## 已知问题和注意事项
### 1. 聊天场景渲染
- 聊天内容使用 `dangerouslySetInnerHTML` 渲染HTML字符串
- 深度思考区域支持点击展开/折叠
- 聊天输入框仅为展示,无实际功能
### 2. 浏览器兼容性
- 需要现代浏览器(Chrome、Firefox、Safari、Edge)
- 不支持IE
- file://协议下可能存在某些限制
### 3. 状态持久化
- 使用localStorage存储子页面状态
- 清除浏览器数据会丢失导航状态
- 不同浏览器标签页共享localStorage
### 4. 性能考虑
- 单个HTML文件较大,首次加载可能稍慢
- 所有图标已通过react-icons优化,按需加载
- SCSS样式已编译为CSS,无运行时开销
### 5. 构建警告
- 构建时会显示弃用警告:`WARN inlineDynamicImports option is deprecated, please use codeSplitting: false instead.`
- 这个警告来自 `vite-plugin-singlefile` 插件内部,无法通过配置消除
- 警告不影响功能,可以安全忽略
## 开发建议
### 添加新页面
1. 在 `src/pages/` 目录下创建页面组件
2. 在父页面组件(如ConsolePage、AdminPage)中添加路由逻辑
3. 如果需要持久化状态,添加localStorage逻辑
4. 在 `src/styles/global.scss` 中添加页面特定样式
### 添加新组件
1. 在 `src/components/` 目录下创建组件
2. 在 `src/styles/global.scss` 中添加组件样式
3. 使用设计系统变量保持一致性
### 修改样式
1. 优先修改 `src/styles/_variables.scss` 中的变量
2. 添加新的混入到 `src/styles/_mixins.scss`
3. 组件样式添加到 `_components.scss`
4. 页面特定样式添加到 `global.scss`
*最后更新:2026-03-19*