- 新增审核管理页面:版本审核列表、下架审核列表、审核详情页 - 完善技能状态机:开发中/已上架/下架审核中/已下架四种状态 - 实现版本审核机制:审核中/通过/拒绝/撤销四种状态 - 更新 README:详细记录技能开发流程与审核机制 - 优化技能详情页:根据状态展示不同操作按钮 - 完善我的技能列表:状态筛选与操作限制 - 新增上传新版本页面:分离版本上传与基本信息编辑 - 更新 openspec 规范:技能审核流程与状态定义
908 lines
32 KiB
Markdown
908 lines
32 KiB
Markdown
# 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 # 全局日志查询
|
||
│ │ ├── console/ # 工作台子页面
|
||
│ │ │ ├── ChatPage.jsx # 聊天页面
|
||
│ │ │ ├── SkillsPage.jsx # 技能市场
|
||
│ │ │ ├── SkillDetailPage.jsx # 技能详情
|
||
│ │ │ ├── LogsPage.jsx # 日志查询
|
||
│ │ │ ├── TasksPage.jsx # 定时任务
|
||
│ │ │ ├── TaskDetailPage.jsx # 任务详情
|
||
│ │ │ ├── AccountPage.jsx # 账号管理
|
||
│ │ │ ├── ProjectsPage.jsx # 项目管理
|
||
│ │ │ ├── MemberConfigPage.jsx # 成员配置
|
||
│ │ │ ├── AddMemberPage.jsx # 增加成员
|
||
│ │ │ ├── ConsoleReviewListPage.jsx # 审核管理列表(NEW)
|
||
│ │ │ └── ConsoleReviewDetailPage.jsx # 审核详情(NEW)
|
||
│ │ └── developer/ # 开发台子页面
|
||
│ │ ├── DevOverviewPage.jsx # 开发者总览
|
||
│ │ ├── MySkillsPage.jsx # 我的技能(筛选+分页)
|
||
│ │ ├── SkillEditorPage.jsx # 技能详情(只读+操作)
|
||
│ │ ├── UploadSkillPage.jsx # 创建技能(基本信息)
|
||
│ │ ├── UpdateSkillInfoPage.jsx # 更新基本信息
|
||
│ │ ├── UploadVersionPage.jsx # 上传新版本(NEW)
|
||
│ │ ├── DevDocsPage.jsx # 开发文档
|
||
│ │ └── DevAccountPage.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)
|
||
- **运营总览**:平台运营指标卡片(用户总数、部门数量、项目数量、今日调用)、异常/待办事项提醒、最近操作日志
|
||
- **审核管理**:版本审核列表与详情、下架审核列表与详情(NEW)
|
||
- **部门管理**:部门列表,支持搜索筛选、新增、编辑、启用/禁用、删除确认
|
||
- **用户管理**:用户列表,支持搜索筛选(关键词/部门/状态)、新增、编辑、启用/禁用、删除确认,角色区分(管理员/开发者/成员)
|
||
- **项目管理**:项目列表,支持搜索筛选、新增、编辑、启用/禁用、删除确认
|
||
- **日志查询**:全局系统日志查询,支持多维度筛选(关键词、用户、部门、类型、状态、时间范围)
|
||
|
||
### 5. 开发台(Developer)
|
||
- **总览**:开发者指标卡片(我的技能总数、已上架、开发中、待审核)、待审核项目列表、最近动态
|
||
- **我的技能**:技能列表,支持关键词搜索、分类筛选、状态筛选(开发中/已上架/下架审核中/已下架)、分页,支持下架(需要先撤回审核中的版本)、删除(已上架需要先下架)
|
||
- **技能详情**:基本信息只读展示、版本历史管理(根据状态展示操作按钮:审核中-撤回审核+下载、审核通过/拒绝/撤销-仅下载、审核拒绝-显示拒绝理由)、技能操作(上传新版本-有审核中版本时禁用、下架技能、删除技能-已上架时禁用)
|
||
- **创建技能**:基本信息表单 + 技能图标选择(移除技能包上传)
|
||
- **更新基本信息**:独立页面编辑技能名称/描述/分类/标签/图标,与版本上传分离
|
||
- **上传新版本**:仅包含版本说明和技能包上传(NEW)
|
||
- **开发文档**:技能开发相关文档
|
||
- **开发者设置**:开发者账号信息
|
||
|
||
## 路由结构
|
||
|
||
项目使用 **HashRouter**,所有路由基于哈希路径,支持直接打开HTML文件运行。
|
||
|
||
### 主要路由
|
||
```
|
||
/ # 首页
|
||
/login # 登录页面
|
||
/console # 工作台
|
||
/admin # 管理台
|
||
/developer # 开发台
|
||
```
|
||
|
||
### 路由配置(App.jsx)
|
||
```jsx
|
||
import { HashRouter as Router, Routes, Route } from 'react-router-dom';
|
||
|
||
<Router>
|
||
<Routes>
|
||
<Route path="/" element={<HomePage />} />
|
||
<Route path="/login" element={<LoginPage />} />
|
||
<Route path="/console" element={<ConsolePage />} />
|
||
<Route path="/admin" element={<AdminPage />} />
|
||
<Route path="/developer" element={<DeveloperPage />} />
|
||
</Routes>
|
||
</Router>
|
||
```
|
||
|
||
## 通用组件
|
||
|
||
### 布局组件
|
||
|
||
#### SidebarBrand 品牌区域
|
||
侧边栏顶部的品牌展示组件。
|
||
|
||
```jsx
|
||
import { SidebarBrand } from '../components/layout/SidebarBrand.jsx';
|
||
|
||
<SidebarBrand subtitle="企业级AI平台" />
|
||
```
|
||
|
||
#### SidebarUser 用户信息
|
||
侧边栏底部的用户信息展示组件,使用全局用户上下文。
|
||
|
||
```jsx
|
||
import { SidebarUser } from '../components/layout/SidebarUser.jsx';
|
||
|
||
<SidebarUser
|
||
onClick={() => 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';
|
||
|
||
<SidebarNavItem
|
||
icon={<FiMessageSquare />}
|
||
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';
|
||
|
||
<EmptyState
|
||
icon={<FiInbox size={48} />}
|
||
title="暂无数据"
|
||
description="当前没有可显示的内容"
|
||
/>
|
||
```
|
||
|
||
#### Modal 弹窗
|
||
用于展示确认操作的弹窗组件,支持自定义标题和内容。
|
||
|
||
```jsx
|
||
import Modal from '../components/common/Modal.jsx';
|
||
|
||
<Modal
|
||
visible={showModal}
|
||
title="确认删除"
|
||
onConfirm={handleConfirm}
|
||
onCancel={handleCancel}
|
||
confirmText="删除"
|
||
>
|
||
确定要删除这个任务吗?
|
||
</Modal>
|
||
```
|
||
|
||
#### Toast 消息提示
|
||
用于展示操作结果的消息提示组件,支持成功、错误、警告、信息四种类型。
|
||
|
||
```jsx
|
||
import Toast from '../components/common/Toast.jsx';
|
||
|
||
<Toast
|
||
visible={showToast}
|
||
type="success"
|
||
message="操作成功"
|
||
onClose={() => setShowToast(false)}
|
||
/>
|
||
```
|
||
|
||
**支持的类型:**
|
||
- `success` - 成功(绿色)
|
||
- `error` - 错误(红色)
|
||
- `warning` - 警告(黄色)
|
||
- `info` - 信息(蓝色)
|
||
|
||
#### StatusBadge 状态标签
|
||
用于显示状态(成功、失败、警告等)的标签组件。
|
||
|
||
```jsx
|
||
import StatusBadge from '../components/common/StatusBadge.jsx';
|
||
|
||
<StatusBadge status="success" text="运行中" />
|
||
<StatusBadge status="error" text="失败" />
|
||
<StatusBadge status="warning" text="警告" />
|
||
<StatusBadge status="stopped" text="已停止" />
|
||
```
|
||
|
||
#### TagInput 标签输入
|
||
支持输入标签的输入框组件。
|
||
|
||
```jsx
|
||
import TagInput from '../components/common/TagInput.jsx';
|
||
|
||
<TagInput
|
||
tags={tags}
|
||
onChange={setTags}
|
||
placeholder="输入标签后按回车添加"
|
||
/>
|
||
```
|
||
|
||
#### SearchBar 搜索框
|
||
通用的搜索输入框组件。
|
||
|
||
```jsx
|
||
import SearchBar from '../components/common/SearchBar.jsx';
|
||
|
||
<SearchBar
|
||
value={searchQuery}
|
||
onChange={setSearchQuery}
|
||
placeholder="搜索..."
|
||
/>
|
||
```
|
||
|
||
### 列表组件
|
||
|
||
#### ListSelector 列表选择器
|
||
通用的列表选择器组件,支持单选和多选模式。
|
||
|
||
```jsx
|
||
import ListSelector from '../components/ListSelector.jsx';
|
||
|
||
<ListSelector
|
||
data={dataList} // 数据数组
|
||
selectedIds={selectedIds} // 已选项
|
||
onChange={handleChange} // 选择变化回调
|
||
searchPlaceholder="搜索..." // 搜索框占位符
|
||
columns={columns} // 列配置 [{ key, label }]
|
||
multiSelect={false} // 是否多选
|
||
selectedLabel="已选标签" // 已选标签文字
|
||
onClearSelected={() => {}} // 清除已选回调
|
||
/>
|
||
```
|
||
|
||
## 状态管理
|
||
|
||
### 全局状态
|
||
|
||
#### UserContext 用户信息上下文
|
||
全局用户信息状态,通过 `UserProvider` 提供给整个应用。
|
||
|
||
```jsx
|
||
import { UserProvider, useUserContext } from '../contexts/UserContext.jsx';
|
||
|
||
// 在 App.jsx 中包裹
|
||
<UserProvider user={{ name: '张三', avatar: '张', role: 'AI 产品部' }}>
|
||
<App />
|
||
</UserProvider>
|
||
|
||
// 在组件中使用
|
||
function Component() {
|
||
const { user } = useUserContext();
|
||
return <div>{user.name}</div>;
|
||
}
|
||
```
|
||
|
||
### 自定义 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', 'overview');
|
||
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`:技能市场数据,包含技能详情(含状态:dev/published/unlisting/unlisted)、文件列表、版本历史(含状态:reviewing/approved/rejected/withdrawn、拒绝理由)、审核列表(pendingVersionReviews、pendingUnlistReviews)
|
||
- `developerData.js`:开发台数据,包含我的技能(含图标、版本审核状态、hasPendingReview标识)、技能分类、开发者总览、开发文档
|
||
- `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`
|
||
|
||
---
|
||
|
||
## 技能开发流程与审核机制
|
||
|
||
### 流程概述
|
||
|
||
技能从创建到上架的完整流程包括:技能创建、版本上传、审核管理、上架销售四个主要环节。
|
||
|
||
### 状态定义
|
||
|
||
#### 技能状态
|
||
|
||
技能有四种状态,表示技能在平台上的可见性和可用性:
|
||
|
||
| 状态 | 英文 | 描述 | 图标样式 |
|
||
|------|------|------|---------|
|
||
| 开发中 | `dev` | 技能已创建但尚未有审核通过的版本 | status-stopped (灰色) |
|
||
| 已上架 | `published` | 技能有审核通过的版本,可在技能市场展示和订阅 | status-running (绿色) |
|
||
| 下架审核中 | `unlisting` | 开发者申请下架,等待管理员审核 | status-warning (黄色) |
|
||
| 已下架 | `unlisted` | 技能已下架,不在技能市场展示,可删除 | status-stopped (灰色) |
|
||
|
||
#### 版本状态
|
||
|
||
版本有四种状态,表示版本在审核流程中的位置:
|
||
|
||
| 状态 | 英文 | 描述 | 图标样式 |
|
||
|------|------|------|---------|
|
||
| 审核中 | `reviewing` | 版本已提交,等待管理员审核 | status-warning (黄色) |
|
||
| 审核通过 | `approved` | 版本审核通过,自动生效,技能可上架 | status-running (绿色) |
|
||
| 审核拒绝 | `rejected` | 版本审核未通过,需修改后重新提交 | status-error (红色) |
|
||
| 已撤销 | `withdrawn` | 开发者主动撤回审核,版本废弃 | status-stopped (灰色) |
|
||
|
||
### 完整流程
|
||
|
||
```
|
||
┌───────────────────────────────────────────────────────────────────┐
|
||
│ 技能开发流程 │
|
||
└───────────────────────────────────────────────────────────────────┘
|
||
|
||
开发者操作 管理员操作 技能市场
|
||
──────────── ─────────── ─────────
|
||
[1. 创建技能] → 技能: 开发中
|
||
│
|
||
↓ (创建后可立即上传版本)
|
||
[2. 上传新版本] → 版本: 审核中
|
||
│ ──────────────────────────▶ [待审核列表]
|
||
↓ │
|
||
[3. 提交审核] ↓
|
||
│ [4. 审核操作]
|
||
├───────────────────────────────────────────────┼───────┐
|
||
│ │ │
|
||
↓ ↓ ↓
|
||
[审核通过] [审核通过] [审核拒绝]
|
||
│ │
|
||
└───────────────────────────────────────────────┘
|
||
↓
|
||
技能: 已上架
|
||
版本: 审核通过(生效)
|
||
│
|
||
───────────────────────────────────────────────────────────▶ [可在技能市场展示]
|
||
|
||
后续操作:
|
||
- [5. 上传新版本] → (需先撤回审核中的版本,一次只能有一个审核中)
|
||
- [6. 下架技能] → (需先撤回审核中的版本,下架需管理员审核)
|
||
- [7. 删除技能] → (已上架的技能必须先下架)
|
||
```
|
||
|
||
### 关键规则
|
||
|
||
#### 1. 版本上传规则
|
||
|
||
- **版本号由后端自动生成**:前端上传时无需填写版本号
|
||
- **上传即进入审核**:版本上传后状态自动变为"审核中",没有"草稿"状态
|
||
- **一次只能有一个审核中的版本**:
|
||
- 如果存在审核中的版本,"上传新版本"按钮禁用
|
||
- 审核通过或撤回后,才能上传新版本
|
||
|
||
#### 2. 审核中版本操作
|
||
|
||
- 可执行操作:撤回审核、下载
|
||
- 撤回审核后,版本状态变为"已撤销"(终态),无法继续操作
|
||
- 如需重新提交,需上传新版本
|
||
|
||
#### 3. 技能操作规则
|
||
|
||
| 技能状态 | 可用操作 | 备注 |
|
||
|---------|---------|------|
|
||
| 开发中 | 更新基本信息、删除技能 | 未上架,可直接删除 |
|
||
| 已上架 | 更新基本信息、下架技能 | 删除按钮禁用(需先下架) |
|
||
| 已上架+有审核中版本 | 更新基本信息 | 下架按钮禁用、上传按钮禁用 |
|
||
| 下架审核中 | 无(等待管理员审核) | 所有操作按钮禁用 |
|
||
| 已下架 | 更新基本信息、删除技能 | 可删除 |
|
||
|
||
#### 4. 下架流程
|
||
|
||
- **下架需要管理员审核**:
|
||
1. 开发者点击"下架技能"
|
||
2. 技能状态变为"下架审核中"
|
||
3. 管理台"审核管理" -> "下架审核"列表中显示
|
||
4. 管理员审核通过/拒绝
|
||
5. 通过:技能状态变为"已下架",技能市场移除
|
||
6. 拒绝:技能状态回到"已上架"
|
||
|
||
- **下架期间禁止操作**:
|
||
- 下架审核中的技能,所有操作按钮禁用
|
||
- 不能上传新版本
|
||
|
||
#### 5. 审核拒绝
|
||
|
||
- 版本审核拒绝后,在版本说明下方显示拒绝理由
|
||
- 被拒绝的版本在技能详情页可见,但无法再次提交审核
|
||
- 开发者需上传新版本重新提交
|
||
|
||
### 数据结构
|
||
|
||
#### 技能数据(skills.js / developerData.js)
|
||
|
||
```javascript
|
||
{
|
||
id: 1,
|
||
name: '代码生成助手',
|
||
desc: '根据需求自动生成高质量代码',
|
||
tags: ['开发', '代码', 'AI'],
|
||
status: 'published', // 技能状态: dev | published | unlisting | unlisted
|
||
hasPendingReview: false, // 是否有审核中的版本
|
||
category: '开发工具',
|
||
versions: [...] // 版本列表
|
||
}
|
||
```
|
||
|
||
#### 版本数据
|
||
|
||
```javascript
|
||
{
|
||
version: 'v1.3.0',
|
||
date: '2026-03-12',
|
||
desc: '新增 Python 3.11 支持',
|
||
status: 'approved', // 版本状态: reviewing | approved | rejected | withdrawn
|
||
rejectionReason: '' // 审核拒绝理由(仅status为rejected时)
|
||
}
|
||
```
|
||
|
||
#### 审核列表数据
|
||
|
||
```javascript
|
||
// 版本审核列表
|
||
pendingVersionReviews = [{
|
||
id: 1,
|
||
skillName: '代码生成助手',
|
||
version: 'v1.4.0',
|
||
date: '2026-03-20',
|
||
developer: '张三'
|
||
}]
|
||
|
||
// 下架审核列表
|
||
pendingUnlistReviews = [{
|
||
id: 1,
|
||
skillName: 'CRM 客户查询',
|
||
currentVersion: 'v1.5.0',
|
||
date: '2026-03-20',
|
||
developer: '赵六'
|
||
}]
|
||
```
|
||
|
||
### 页面交互细节
|
||
|
||
#### 技能详情页(SkillEditorPage)
|
||
|
||
**版本历史表格:**
|
||
|
||
| 版本号 | 版本说明 | 状态 | 更新时间 | 操作 |
|
||
|-------|---------|------|---------|------|
|
||
| v1.3.0 | 新增功能... | 审核通过 | 2026-03-12 | [下载] |
|
||
| v1.2.0 | 优化性能... | 审核拒绝 | 2026-03-08 | [下载] 拒绝理由: 测试用例不完整 |
|
||
| v1.1.0 | 新增支持... | 审核中 | 2026-02-20 | [撤回审核] [下载] |
|
||
|
||
**技能操作按钮:**
|
||
- 更新基本信息:始终可用
|
||
- 上传新版本:有审核中版本时禁用,提示"存在审核中的版本,请先撤回后再上传新版本"
|
||
- 下架技能:技能状态为已上架且无审核中版本时可用
|
||
- 删除技能:技能状态为开发中或已下架时可用,已上架时禁用并提示"已上架的技能需要先下架才能删除"
|
||
|
||
#### 我的技能列表页(MySkillsPage)
|
||
|
||
**状态列展示:**
|
||
- 开发中:显示"开发中"
|
||
- 已上架:显示"已上架"
|
||
- 已上架+有审核中版本:显示"已上架 · 审核中"
|
||
- 下架审核中:显示"下架审核中"
|
||
- 已下架:显示"已下架"
|
||
|
||
**操作列:**
|
||
- 编辑:始终可用
|
||
- 下架技能:已上架且无审核中版本时可用
|
||
- 删除技能:开发中或已下架时可用
|
||
|
||
#### 管理台审核管理(AdminPage - reviewList)
|
||
|
||
**Tab切换:**
|
||
- 版本审核:显示待审核的版本列表
|
||
- 下架审核:显示待审核的下架申请列表
|
||
|
||
**版本审核列表:**
|
||
| 技能名称 | 版本号 | 提交时间 | 开发者 | 操作 |
|
||
|---------|-------|---------|--------|------|
|
||
| 代码生成助手 | v1.4.0 | 2026-03-20 | 张三 | [审核] |
|
||
|
||
**审核详情页(reviewDetail):**
|
||
|
||
**版本审核详情:**
|
||
- 基本信息:技能名称、开发者、分类、标签
|
||
- 版本信息:版本号、提交时间、版本说明
|
||
- 文件列表:显示技能包包含的文件
|
||
- 操作:[拒绝] [通过]
|
||
|
||
**下架审核详情:**
|
||
- 技能信息:技能名称、开发者、当前版本、订阅数、申请时间
|
||
- 操作:[拒绝] [通过]
|
||
|
||
#### 技能市场详情页(SkillDetailPage)
|
||
|
||
**版本展示:**
|
||
- 只显示最新审核通过版本的信息
|
||
- 不展示完整版本历史
|
||
- 示例:
|
||
```
|
||
当前版本: v1.3.0
|
||
更新说明: 新增 Python 3.11 支持
|
||
更新时间: 2026-03-12
|
||
```
|
||
|
||
### 状态映射关系
|
||
|
||
```javascript
|
||
// 技能状态映射
|
||
const skillStatusMap = {
|
||
dev: { text: '开发中', className: 'status-stopped' },
|
||
published: { text: '已上架', className: 'status-running' },
|
||
unlisting: { text: '下架审核中', className: 'status-warning' },
|
||
unlisted: { text: '已下架', className: 'status-stopped' }
|
||
};
|
||
|
||
// 版本状态映射
|
||
const versionStatusMap = {
|
||
reviewing: { text: '审核中', className: 'status-warning' },
|
||
approved: { text: '审核通过', className: 'status-running' },
|
||
rejected: { text: '审核拒绝', className: 'status-error' },
|
||
withdrawn: { text: '已撤销', className: 'status-stopped' }
|
||
};
|
||
```
|
||
|
||
### 注意事项
|
||
|
||
1. **原型说明**:本页面为静态原型,所有交互均为前端模拟,未连接真实后端
|
||
2. **状态持久化**:页面刷新后,状态会重置为初始值
|
||
3. **按钮禁用**:使用 HTML 原生 `disabled` 属性,配合 `title` 提示显示禁用原因
|
||
4. **Modal 确认**:删除和下架操作需要二次确认,使用 Modal 组件展示确认对话框
|
||
5. **Toast 提示**:操作完成后显示 Toast 提示,展示操作结果(成功/失败)
|
||
|
||
*最后更新:2026-03-20*
|