# 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预处理器 - **五层分层架构**:tokens → core → layouts → components → pages - **BEM 命名规范**:所有组件类名遵循 `.block__element--modifier` 格式 ### 构建优化 - **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 # 管理台数据(部门/用户/项目/总览/日志/模型配置) │ │ └── configTypes.js # 模型配置类型注册表 │ ├── pages/ # 页面组件 │ │ ├── HomePage.jsx # 首页 │ │ ├── LoginPage.jsx # 登录页面 │ │ ├── ConsolePage.jsx # 工作台主页面 │ │ ├── AdminPage.jsx # 管理台主页面 │ │ ├── DeveloperPage.jsx # 开发台主页面 │ │ ├── console/ # 工作台子页面 │ │ ├── admin/ # 管理台子页面 │ │ └── developer/ # 开发台子页面 │ └── styles/ # SCSS样式系统(分层架构) │ ├── tokens/ # 第1层:设计令牌 │ │ ├── _colors.scss # 品牌色、功能色、中性色 │ │ ├── _spacing.scss # 间距系统(4px基数) │ │ ├── _shadows.scss # 阴影层级 │ │ ├── _radius.scss # 圆角系统 │ │ ├── _typography.scss # 字体、字号、字重 │ │ ├── _z-index.scss # 层级系统 │ │ ├── _transitions.scss # 过渡动画参数 │ │ ├── _breakpoints.scss # 响应式断点 │ │ ├── _mixins.scss # 可复用混入 │ │ └── _index.scss # 统一导出 │ ├── core/ # 第2层:核心样式 │ │ ├── _reset.scss # CSS重置 │ │ ├── _css-variables.scss # :root CSS变量 │ │ ├── _base.scss # body全局样式 │ │ └── _index.scss │ ├── layouts/ # 第3层:布局系统 │ │ ├── _app-shell.scss # 主框架(sidebar+header+main) │ │ ├── _chat-layout.scss # 聊天页面布局 │ │ ├── _admin-layout.scss # 管理台布局 │ │ └── _index.scss │ ├── components/ # 第4层:组件库 │ │ ├── button/ # 按钮(.btn, .btn--primary, .btn--ghost) │ │ ├── card/ # 卡片(.card, .card__header, .card__body) │ │ ├── table/ # 表格(.table, .table-actions, .col-actions) │ │ ├── form/ # 表单(.form-group, .form__input, .form__label) │ │ ├── tag/ # 标签(.tag--running, .tag--admin) │ │ ├── modal/ # 弹窗(.modal, .modal__overlay) │ │ ├── toast/ # 提示(.toast--success, .toast--error) │ │ ├── pagination/ # 分页 │ │ ├── empty-state/ # 空状态 │ │ ├── switch/ # 开关 │ │ ├── skill-card/ # 技能卡片 │ │ ├── nav/ # 导航项 │ │ ├── detail/ # 详情页组件 │ │ ├── password-input/ # 密码输入框 │ │ ├── search-bar/ # 搜索栏 │ │ ├── stat-card/ # 统计卡片 │ │ └── _index.scss # 统一导出 │ ├── pages/ # 第5层:页面特有样式 │ │ ├── _console.scss # 工作台特有组件 │ │ ├── _admin.scss # 管理台特有组件 │ │ ├── _developer.scss # 开发台特有组件 │ │ ├── _home.scss # 首页特有组件 │ │ └── _index.scss │ └── global.scss # 主入口文件(仅 @use,无直接样式) ├── 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) - **聊天界面**:支持多种聊天场景(欢迎页、普通对话、技能调用、文件上传) - **技能市场**:浏览已上架技能、订阅技能(仅展示已上架技能) - **我的技能**:管理已订阅技能,支持启用/禁用、配置变量、取消订阅(NEW) - **技能配置**:为已订阅技能配置 key-value 变量(NEW) - **日志查询**:支持按用户、类型、状态筛选 - **定时任务**:管理定时任务,支持启用/禁用,查看任务详情 - **项目管理**:成员列表,增加成员 - **账号管理**:个人信息和密码修改 ### 4. 管理台(Admin) - **运营总览**:平台运营指标卡片(用户总数、部门数量、项目数量、今日调用)、异常/待办事项提醒、最近操作日志 - **审核管理**:版本审核列表与详情、下架审核列表与详情 - **部门管理**:部门列表,支持搜索筛选、新增、编辑、启用/禁用、删除确认 - **用户管理**:用户列表,支持搜索筛选(关键词/部门/状态)、新增、编辑、启用/禁用、删除确认,角色区分(管理员/开发者/成员) - **项目管理**:项目列表,支持搜索筛选、新增、编辑、启用/禁用、删除确认 - **模型配置**:管理平台的默认模型接入配置,支持多组配置(OpenAI兼容接口、智算管理平台等类型),可切换生效配置,生效中配置不可编辑/删除,配置类型创建后不可修改 - **日志查询**:全局系统日志查询,支持多维度筛选(关键词、用户、部门、类型、状态、时间范围) ### 5. 开发台(Developer) - **总览**:开发者指标卡片(我的技能总数、已上架、开发中、待审核)、待审核项目列表、最近动态 - **我的技能**:技能列表,支持关键词搜索(内部名称/内部描述)、状态筛选(开发中/已上架/下架审核中/已下架)、分页,支持下架(需要先撤回审核中的版本)、删除(已上架需要先下架),仅展示开发者内部信息 - **技能详情**:四段式布局 - 1) 概览卡片(内部信息:内部名称、状态、编辑按钮);2) 当前生效版本卡片(商店展示效果预览,分类作为第一个标签显示);3) 版本历史卡片(普通卡片布局,展示版本号、状态、日期、版本说明、发布信息预览、操作按钮,无下载按钮);4) 管理操作卡片 - **创建技能**:简化表单 - 仅内部技能名称、内部技能描述(明确标注仅供开发者管理使用) - **编辑内部信息**:独立页面编辑内部技能名称/内部技能描述(明确标注不影响商店展示) - **上传新版本**:增强表单 - 版本说明区域 + 发布信息区域(技能发布名称、技能发布描述、分类、标签、图标),非首版本默认继承当前生效版本的值 - **开发文档**:技能开发相关文档 - **开发者设置**:开发者账号信息 #### 重要数据结构变更说明 - **开发者内部信息**:内部名称、内部描述 - 仅供开发者管理,与商店展示完全无关,可随时修改无需审核 - **版本发布信息**:发布名称、发布描述、分类、标签、图标 - 存储在版本中,随版本审核通过后生效,修改必须发布新版本 - **技能商店展示**:完全从当前生效版本取发布信息,确保任何商店内容变更都经过版本审核 - **分类与标签展示**:分类始终作为第一个标签显示,与普通标签一起展示 #### 按钮禁用规则 基于 `hasPendingReview` 标志和技能状态控制操作按钮可用性: - **上传新版本按钮**:`status === 'unlisting' || status === 'unlisted' || hasPendingReview === true` 时禁用 - **下架技能按钮**:`hasPendingReview === true` 时禁用 - **删除技能按钮**:`status === 'published' || status === 'unlisting' || hasPendingReview === true` 时禁用 #### 撤回审核按钮样式 - **按钮类型**:警告按钮(橙色) - **按钮类名**:`btn btn-warning btn-sm` - **按钮图标**:逆时针旋转图标(FiRotateCcw) - **按钮文案**:"撤回审核" - **展示位置**:版本历史卡片中审核中版本的操作区域 ## 路由结构 项目使用 **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', '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'; }); ``` ## 样式系统 ### 分层架构 样式采用五层架构,依赖方向自上而下:`tokens → core → layouts → components → pages` ``` ┌─────────────────────────────────────────┐ │ pages/ 页面特有组件,仅覆盖模式 │ ← 最上层 ├─────────────────────────────────────────┤ │ components/ 可复用UI组件库,BEM命名 │ ├─────────────────────────────────────────┤ │ layouts/ 布局系统(shell/chat/admin) │ ├─────────────────────────────────────────┤ │ core/ 重置、CSS变量、body样式 │ ├─────────────────────────────────────────┤ │ tokens/ 设计令牌(颜色/间距/阴影...) │ ← 最底层 └─────────────────────────────────────────┘ ``` ### 第1层:Tokens(设计令牌) 所有设计决策集中定义,禁止在组件或页面中硬编码值。 ```scss // src/styles/tokens/_colors.scss $primary: #3B82F6; $primary-dark: #2563EB; $success: #10B981; $danger: #EF4444; $text-1: #1E293B; $text-3: #94A3B8; // src/styles/tokens/_spacing.scss $spacing-1: 4px; $spacing-2: 8px; $spacing-4: 16px; // src/styles/tokens/_typography.scss $font-size-base: 14px; $font-weight-semibold: 600; ``` **使用方式:** 通过 `@use` 引入,直接使用变量名。 ```scss @use '../../tokens' as *; .my-component { color: $text-1; padding: $spacing-4; font-weight: $font-weight-semibold; } ``` **同时提供 CSS 变量**(core 层定义),供运行时和 JSX 内联场景使用: ```scss // core/_css-variables.scss 自动从 tokens 生成 :root 变量 :root { --color-primary: #{$primary}; --color-text-1: #{$text-1}; } // JSX 中可通过 style 使用
``` ### 第2层:Core(核心样式) 包含 CSS 重置、`:root` CSS 变量定义、body 全局样式。无业务逻辑。 ``` core/ ├── _reset.scss # * { margin:0; padding:0; box-sizing:border-box; } ├── _css-variables.scss # :root { --color-primary: ...; } ├── _base.scss # body { font-family, color, background } └── _index.scss # @forward 所有 core 模块 ``` ### 第3层:Layouts(布局系统) 页面骨架布局,不包含具体UI组件样式。 | 文件 | 职责 | |------|------| | `_app-shell.scss` | 主框架:sidebar + header + main-content + 响应式 | | `_chat-layout.scss` | 聊天页:chat-sidebar + chat-content + conversation-list | | `_admin-layout.scss` | 管理台:admin-sidebar + admin-nav + member-selection | **关键类名:** - `.layout` / `.app-shell` — 主布局容器 - `.sidebar` — 侧边栏 - `.main-content` — 主内容区 - `.header` — 顶部栏 - `.page-content` — 页面内容区 ### 第4层:Components(组件库) 每个组件一个目录,内部 `_index.scss` 包含该组件的完整样式。 ``` components/ ├── button/_index.scss ├── card/_index.scss ├── table/_index.scss ├── form/_index.scss ├── tag/_index.scss ├── modal/_index.scss ├── toast/_index.scss └── _index.scss # @forward 所有组件 ``` **组件目录创建规则:** ``` components/ └── {component-name}/ └── _index.scss # 必须存在,包含组件全部样式 ``` ### 第5层:Pages(页面特有样式) 仅包含**页面独有的组件样式**,不放可复用组件。 ``` pages/ ├── _console.scss # 聊天消息、欢迎区、输入框等 ├── _admin.scss # 总览统计、异常列表等 ├── _developer.scss # 技能概览卡片、版本历史卡片等 ├── _home.scss # 首页英雄区、特性卡片等 └── _index.scss ``` ### 主入口文件 `global.scss` 是纯入口文件,**仅包含 `@use` 语句**,无任何直接样式定义: ```scss // src/styles/global.scss @use 'tokens' as *; @use 'core' as *; @use 'layouts' as *; @use 'components' as *; @use 'pages/console' as *; @use 'pages/admin' as *; @use 'pages/developer' as *; @use 'pages/home' as *; ``` --- ## 样式开发规范 ### BEM 命名规范 所有组件类名必须遵循 BEM 格式:`.block__element--modifier` ```scss // Block — 组件根节点 .card { } // Element — 组件内部元素,用双下划线连接 .card__header { } .card__body { } .card__footer { } // Modifier — 变体/状态,用双连字符连接 .card--flat { } .card--elevated { } .btn--primary { } .btn--danger { } .tag--running { } .tag--admin { } ``` **JSX 对应写法:** ```jsx
标题
内容
运行中 ``` ### 组件文件内部结构 每个组件的 `_index.scss` 按以下顺序组织: ```scss // 1. 依赖引入 @use '../../tokens' as *; // 2. Block — 组件根节点 .btn { } // 3. Elements — 内部元素 .btn__icon { } // 4. Modifiers — 变体(按语义分组) // 颜色变体 .btn--primary { } .btn--danger { } // 尺寸变体 .btn--sm { } .btn--lg { } // 状态变体 .btn--loading { } // 5. Legacy 兼容别名(过渡期) .text-btn { @extend .btn--ghost; } ``` ### 新增组件开发流程 1. **确认组件层级**:属于 tokens/core/layouts/components/pages 哪一层 2. **创建目录**:`src/styles/components/{name}/` 3. **创建 `_index.scss`**:按 BEM 结构编写样式 4. **引入 tokens**:`@use '../../tokens' as *;` 使用设计令牌 5. **在 `_index.scss` 中注册**:`components/_index.scss` 添加 `@forward '{name}';` 6. **在 JSX 中使用**:`className="block__element--modifier"` 7. **验证构建**:`pnpm build` ### 新增页面样式开发流程 1. **优先复用组件库**:先检查 `components/` 是否已有可用组件 2. **页面特有组件**:在 `pages/_{page}.scss` 中定义 3. **仅放页面独有的样式**:可复用的应提取到 `components/` 4. **不硬编码值**:使用 tokens 中的变量或 CSS 变量 ### 内联样式规则 **禁止使用内联 style 的场景:** - 可复用的组件样式(按钮、卡片、表格操作列等) - 使用 tokens 中已有变量的值 - 多个页面/组件中重复出现的模式 **允许使用内联 style 的场景:** - 各表特有的内容列宽(如 `style={{ width: '180px' }}`) - 动态计算值(如进度条宽度 `width: 65%`) - 聊天消息内容中的排版(通过 `dangerouslySetInnerHTML` 渲染) ### 表格操作列规范 表格操作列统一使用以下类名,禁止写内联样式: ```jsx // 表头 — 操作列宽度 操作 // 200px 操作 // 120px 操作 // 80px // 单元格 — 操作按钮容器
// 可点击行 ``` ### 按钮使用规范 | 场景 | 类名 | 颜色 | |------|------|------| | 主操作(确认、提交) | `btn btn--primary` | 蓝色实心 | | 次要操作(取消、重置) | `btn` | 灰色边框 | | 表格内编辑 | `text-btn text-btn-primary` | 蓝色文字 | | 表格内删除/禁用 | `text-btn text-btn-danger` | 红色文字 | | 危险操作确认 | `btn btn--danger` | 红色实心 | | 警告操作 | `btn btn--warning` | 橙色实心 | ### 状态标签规范 ```jsx // 运行状态 运行中 已停止 失败 警告 // 用户角色 管理员 成员 开发者 ``` ### 引用 Tokens 的方式 ```scss // 在组件或页面文件中 @use '../../tokens' as *; // 直接使用 SCSS 变量 .my-class { color: $primary; padding: $spacing-4; border-radius: $radius-md; font-weight: $font-weight-semibold; box-shadow: $shadow-card; } // 使用 CSS 变量(适合需要运行时切换的场景) .my-class { color: var(--color-primary); background: var(--color-bg-1); } ``` ### 样式文件引用规则 ```scss // tokens 层:无依赖 @use 'colors' as *; // core 层:依赖 tokens @use '../tokens' as *; // layouts 层:依赖 tokens @use '../tokens' as *; // components 层:依赖 tokens @use '../../tokens' as *; // pages 层:依赖 tokens @use '../tokens' as *; ``` **禁止**:跨层引用(如 components 直接引用 pages) ### 响应式开发 使用 tokens 中定义的断点,通过 mixins 调用: ```scss @use '../../tokens' as *; @include mobile { // <= 768px .my-component { flex-direction: column; } } @include tablet { // 769px ~ 1024px } @include desktop { // >= 1025px } ``` ## 数据访问层 项目使用统一的数据访问接口 `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`:管理台数据(部门列表、用户列表、项目列表、模型配置列表、总览指标、全局日志、可选项数据) - `configTypes.js`:模型配置类型注册表(OpenAI兼容接口、智算管理平台等类型定义) - `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/pages/_{module}.scss`(优先复用组件库) ### 添加新组件 1. 在 `src/components/` 目录下创建组件 2. 在 `src/styles/components/{name}/` 下创建 `_index.scss` 3. 使用 `@use '../../tokens' as *;` 引入设计令牌 4. 使用 BEM 命名:`.block__element--modifier` 5. 在 `src/styles/components/_index.scss` 中添加 `@forward '{name}';` ### 修改样式 1. **全局调整**:修改 `src/styles/tokens/` 中的令牌变量 2. **组件调整**:修改 `src/styles/components/{name}/_index.scss` 3. **页面调整**:修改 `src/styles/pages/_{module}.scss` 4. 禁止直接修改 `global.scss`(它是纯入口文件) ### 样式验证清单 - [ ] 类名是否遵循 BEM 规范 - [ ] 颜色/间距/字号是否使用 tokens 变量 - [ ] 是否存在重复定义的样式 - [ ] 可复用样式是否放在 `components/` 而非 `pages/` - [ ] 表格操作列是否使用 `.col-actions` + `.table-actions` - [ ] `pnpm build` 是否通过 --- ## 更多文档 审核审批流程的详细说明请查看:[docs/审核流程.md](docs/审核流程.md) *最后更新:2026-03-26*