Files
Developer ebb8fbd298 docs: 统一 CLAUDE.md 和 README.md 文档体系
CLAUDE.md(AI 参考):
- 4 个 👉 AI 实现参考 标记,AI 可快速定位
- 完整的实体定义(TypeScript 代码块)
- 权限守卫流水线 + 解析链路
- 考核数据模型 + 出题算法伪代码
- API 认证流程 + 关键端点表
- 测试注意事项(React 受控输入/等待策略)
- 人可读用户指南(与 README 一致)

README.md(人可读):
- 顶部引用 CLAUDE.md — AI 阅读指引
- 功能亮点表格式呈现
- 步骤式操作指南(用户/权限/模板/考试/租户)
- 轻量内容,详细技术参考指向 CLAUDE.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 13:29:28 +08:00

487 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AuraK — 项目指南
> 本文件同时服务于 AI 助手(Claude Code / OpenCode / Codex / Gemini CLI)和人类开发者。
> 阅读者可根据 `👉 AI 提示` 标记的章节快速定位 AI 需要的信息。
---
## 一、项目速览
**AuraK** 是企业级多租户 AI 知识库与人才评价平台。
| 项目 | 说明 |
|---|---|
| 前端 | React 19 + TypeScript + Vite 6 → 端口 13001 |
| 后端 | NestJS 11 + TypeScript → 端口 3001 |
| 数据库 | SQLite`server/data/metadata.db`+ Elasticsearch 9 |
| 认证 | JWT + API Key 双机制 |
| AI 引擎 | LangChain + LangGraph |
| 部署 | Docker Compose + Nginx |
### 技术栈全景
```
Frontend: React 19 / TypeScript / Vite 6 / Tailwind CSS v4 / Framer Motion / Lucide icons
Backend: NestJS 11 / TypeORM / LangChain / LangGraph / Passport (JWT)
Database: better-sqlite3 (metadata) + Elasticsearch 9 (vector + full-text search)
AI APIs: OpenAI-compatible (DeepSeek, Claude) + Google Gemini native
Infra: Docker Compose (Elasticsearch, Apache Tika, LibreOffice)
```
### 快速命令
```shell
# 启动
cd /d/AuraK/server && node dist/main.js & # 后端
cd /d/AuraK/web && npx vite --port 13001 & # 前端
# 编译
cd /d/AuraK/server && npx nest build # 后端编译
cd /d/AuraK/web && npx vite build # 前端编译
# 测试
cd /d/AuraK && node test-systematic.mjs # 142 项全面测试
# 杀进程(Windows
taskkill //F //IM node.exe 2>/dev/null
```
---
## 二、项目结构
```
AuraK/
├── web/ # React 前端
│ ├── components/
│ │ ├── views/ # 主要页面视图
│ │ │ ├── SettingsView.tsx # 系统设置
│ │ │ ├── PermissionSettingsView.tsx # RBAC 权限矩阵
│ │ │ ├── AssessmentView.tsx # 考核流程
│ │ │ └── AssessmentTemplateManager.tsx # 考核模板编辑
│ │ ├── LoginPage.tsx # 登录页
│ │ └── PermissionGate.tsx # 组件级权限门控
│ ├── src/
│ │ ├── contexts/AuthContext.tsx # 认证/租户上下文
│ │ ├── hooks/usePermissions.ts # 权限 Hook
│ │ └── services/ # API 客户端
│ └── index.tsx # 路由入口
├── server/ # NestJS 后端
│ ├── src/
│ │ ├── auth/ # 认证 + 权限
│ │ │ ├── permission/ # RBAC 模块(详见第 4 章)
│ │ │ ├── roles.guard.ts # @Roles() 守卫
│ │ │ └── combined-auth.guard.ts # 全局认证守卫
│ │ ├── assessment/ # 考核评估(详见第 5 章)
│ │ ├── user/ # 用户 CRUD
│ │ ├── tenant/ # 多租户管理
│ │ └── app.module.ts # 根模块(27 个子模块)
├── docker-compose.yml
├── test-*.mjs # Playwright 测试脚本(8 个)
├── CLAUDE.md / README.md / README_ZH.md # 本文件
└── STARTUP.md / AGENTS.md / VERSION.md
```
---
## 三、系统功能
### 3.1 多租户与用户系统
| 角色 | 权限数 | 核心能力 |
|---|---|---|
| **SUPER_ADMIN** | 26 项 | 全部权限:用户/租户/知识库/考核/模型/设置 |
| **TENANT_ADMIN** | 21 项 | 本租户管理:用户/知识库/考核/模型;不能跨租户、删用户、改系统设置 |
| **USER** | 5 项 | 使用知识库、参与考核、查看插件 |
### 3.2 考核评估系统
- **AI 出题**:从知识库提取素材生成题目,支持选择题/简答/判断题,3:7 比例
- **题库系统**:预置题目 + AI 实时生成双来源,审核发布流程
- **多轮对话**:AI 对简答可发起追问,模拟真实面试
- **模板引擎**:可配置维度/权重/题数/及格分/时限
- **证书系统**:自动生成等级证书(Novice/Proficient/Advanced/Expert
### 3.3 知识库与 AI 对话
- 双处理模式(Tika 快速 / Vision Pipeline 高精度)
- 混合检索(BM25 + 向量 + Rerank
- SSE 流式响应
---
## 四、权限系统(RBAC)— 👉 AI 实现参考
### 4.1 权限定义
位于 `server/src/auth/permission/permission.constants.ts`
| 分类 | 权限 | 说明 |
|---|---|---|
| 用户管理 | `user:view / :create / :edit / :delete / :role / :password` | 用户 CRUD + 角色变更 + 密码重置 |
| 租户管理 | `tenant:view / :create / :edit / :delete / :members` | 租户 CRUD + 成员管理 |
| 知识库 | `kb:view / :create / :edit / :delete / :publish` | 知识库全生命周期 |
| 考核 | `assess:view / :manage / :template / :bank` | 考核查看/管理/模板/题库 |
| 模型 | `model:view / :config` | 模型配置查看/修改 |
| 插件 | `plugin:view / :manage` | 插件查看/启停 |
| 设置 | `settings:view / :system` | 系统设置查看/修改 |
### 4.2 实体模型
```typescript
// Role 实体
@Entity('roles')
class Role {
id: string; name: string; description?: string;
isSystem: boolean; // 系统角色不可删改
baseRole: UserRole | null; // 映射到 UserRole 枚举
tenantId: string | null; // null=全局, 非null=租户自定义
}
// RolePermission 关联
@Entity('role_permissions')
class RolePermission {
roleId: string Role.id;
permissionKey: string; // 如 'user:view'
}
// TenantMember 实体(已有)
@Entity('tenant_members')
class TenantMember {
userId: string User.id;
tenantId: string Tenant.id;
role: UserRole; // SUPER_ADMIN / TENANT_ADMIN / USER
}
```
### 4.3 守卫流水线
```
CombinedAuthGuard (全局 APP_GUARD) → API Key 或 JWT 认证
→ RolesGuard (@Roles(SUPER_ADMIN)) → 角色级门控
→ PermissionsGuard (@Permission('user:view')) → 权限级门控
```
### 4.4 权限解析链路
```
PermissionService.getUserPermissions(userId, tenantId):
1. 查 user.isAdmin → true 则返回全部权限
2. 查 TenantMember(userId, tenantId) → 获取 role
3. 查 Role(baseRole=role, isSystem=true) → 获取 roleId
4. 查 RolePermission(roleId) → 返回权限 Set
```
### 4.5 权限装饰器用法
```typescript
// 后端——标记路由需要的权限(OR 关系)
@Post()
@UseGuards(PermissionsGuard)
@Permission('user:create')
async createUser(...) { ... }
// 前端——组件级门控
<PermissionGate permission="user:create">
<Button></Button>
</PermissionGate>
// 前端——条件渲染
const { hasPermission } = usePermissions();
{hasPermission('user:delete') && <DeleteButton />}
```
### 4.6 系统角色保护
`setRolePermissions()` 加了 `if (role.isSystem) throw Error`
系统角色的名、权限、存在性均不可通过 API 修改。
---
## 五、考核评估系统 — 👉 AI 实现参考
### 5.1 数据模型
```typescript
AssessmentTemplate: id, name, question_count, dimensions[{name,label,weight}],
passingScore(60=6.0/10); perQuestionTimeLimit(300s); totalTimeLimit(1800s)
QuestionBank: id, templateId(unique), items[]
QuestionBankItem: id, type(SHORT_ANSWER|MULTIPLE_CHOICE|TRUE_FALSE),
dimension(PROMPT|LLM|IDE|DEV_PATTERN|WORK_CAPABILITY),
difficulty(STANDARD|ADVANCED|SPECIALIST), status(PUBLISHED|...)
AssessmentSession: id, userId, status(IN_PROGRESS|COMPLETED),
questions_json[], messages[], scores, finalScore, finalReport, passed
AssessmentQuestion: content, keyPoints
AssessmentAnswer: userAnswer, score, feedback, isFollowUp
AssessmentCertificate: id, userId, sessionId, level(Novice|Proficient|Advanced|Expert),
totalScore, dimensionScores, passed
```
### 5.2 出题算法 (`selectQuestions`)
```typescript
selectQuestions(bankId, count, dimensionWeights):
// 1. floor + remainder 分配(保证 sum = count
// 各维度 target = floor(count × weight / totalWeight)
// remainder = count - sum(targets),按权重降序分配
// 2. 各维度池 shuffle 后抽 target 道
// 3. 不足时从剩余池随机补足
// 4. 最终 shuffleArray 返回
// 20题模板示例:
// PROMPT(30%)→6, LLM(30%)→6, IDE(20%)→4, DEV_PATTERN(20%)→4
```
### 5.3 考核流程
```
startSession():
1. 判断是否有关联题库(QuestionBank),且已发布题数 >= targetCount
2. 是 → 从题库抽题(selectQuestions
3. 否 → AI 实时生成(LangGraph 工作流)
4. 创建 AssessmentSession,缓存 questions_json
submitAnswer():
1. 检查时间限制
2. 将答案送入 LangGraph → AI 评分
3. 如需追问 → 设置追问状态 → 等待用户再次提交
4. 所有题答完 → 生成 finalReport → 计算分数
5. finalScore = 带权平均(按风格维度)
passingScore ≥ X/10 → passed = true
```
---
## 六、认证与 API — 👉 AI 实现参考
### 6.1 认证流程
```
密码登录:
POST /api/auth/login (username, password)
→ LocalAuthGuard → JwtService.sign({ username, sub, role, tenantId })
→ 返回 { access_token, user }
获取 API Key:
GET /api/users/api-key (Authorization: Bearer <JWT>)
→ 返回 kb_xxxxxxxx...(前端存 localStorage
后续请求:
Headers: { x-api-key: <apiKey>, x-tenant-id: <tenantId> }
```
### 6.2 全局守卫
`CombinedAuthGuard` 注册为 `APP_GUARD`
- 优先 API Key 认证(`x-api-key` header 或 `Authorization: Bearer kb_*`
- 回退 JWT 认证
- `@Public()` 装饰器跳过认证
- 设置 `request.user = { id, username, role, tenantId }`
### 6.3 关键 API 端点
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| POST | `/api/auth/login` | 公开 | 密码登录 |
| GET | `/api/users` | `user:view` | 用户列表 |
| POST | `/api/users` | `user:create` | 创建用户 |
| PUT | `/api/users/:id` | `user:edit` | 编辑用户 |
| DELETE | `/api/users/:id` | `user:delete` | 删除用户 |
| GET | `/api/permissions/mine` | 认证 | 当前用户权限 |
| GET | `/api/roles` | `TENANT_ADMIN+` | 角色列表 |
| POST | `/api/roles` | `TENANT_ADMIN+` | 创建角色 |
| PUT | `/api/roles/:id/permissions` | `TENANT_ADMIN+` | 设角色权限 |
| GET | `/api/assessment/templates` | 认证 | 考核模板列表 |
| POST | `/api/assessment/start` | 认证 | 开始考核 |
| POST | `/api/assessment/:id/answer` | 认证 | 提交答案 |
---
## 七、测试脚本
所有 Playwright 测试在项目根目录,以 `test-*.mjs` 命名:
| 测试 | 覆盖 | 运行 |
|---|---|---|
| `test-systematic.mjs` | 142 项:认证/CRUD/RBAC/边界/UI | `node test-systematic.mjs` |
| `test-e2e-full.mjs` | 94 项:全角色 E2E | `node test-e2e-full.mjs` |
| `test-user-lifecycle.mjs` | 42 项:用户生命周期 + 异常 | `node test-user-lifecycle.mjs` |
| `test-permission-flow.mjs` | 3 角色权限边界 | `node test-permission-flow.mjs` |
| `test-multiround.mjs` | 考核多轮对话 | `node test-multiround.mjs` |
| `test-question-distribution.mjs` | 出题算法验证 | `node test-question-distribution.mjs` |
| `exam-organizer.mjs` | 考试组织全流程 | `node exam-organizer.mjs` |
### 👉 AI 编写测试注意事项
**React 受控输入框** — 不要用 `type()``fill()`,用 native setter
```javascript
await page.evaluate((text) => {
const ta = document.querySelector('textarea');
if (!ta) return;
const setter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')?.set;
setter?.call(ta, text);
ta.dispatchEvent(new Event('input', { bubbles: true }));
}, '输入文字');
```
**等待 button 可用**
```javascript
await page.waitForFunction(() => {
const btn = document.querySelector('button:has(svg.lucide-send)');
return btn && !btn.disabled;
}, { timeout: 10000 });
```
**等待 spinner 消失**
```javascript
await page.waitForFunction(() => !document.querySelector('.animate-spin'), { timeout: 60000 });
```
**检测考核题型**
```javascript
const state = await page.evaluate(() => {
const optionBtns = Array.from(document.querySelectorAll('button.w-full.text-left.px-5.py-4'))
.filter(b => !b.textContent?.includes('确认答案'));
const ta = document.querySelector('textarea');
return { choiceCount: optionBtns.length, hasTextarea: ta?.offsetParent !== null };
});
```
---
## 八、用户指南(人可读)
### 8.1 用户管理
```
系统设置 → 用户管理
```
- 创建用户:用户名 + 密码 + 显示名
- 编辑用户:修改基本信息、分配角色(USER / TENANT_ADMIN / SUPER_ADMIN
- 删除用户:不可删自己、不可删内置 admin 账号
- 角色变更即时生效(不需要重新登录)
### 8.2 权限管理
```
系统设置 → 权限管理
```
- 左侧角色列表:SUPER_ADMIN / TENANT_ADMIN / USER + 自定义角色
- 点击角色 → 右侧显示该角色的权限矩阵 → 勾选/取消权限 → 保存
- 系统角色(SUPER_ADMIN 等)不可修改、不可删除
- 自定义角色:创建 → 设权限 → 在用户管理中分配给用户
### 8.3 考核模板配置
```
系统设置 → 测评模板
```
- **技术人员模板**(默认):
- PROMPT 30%、LLM 30%、IDE 20%、DEV_PATTERN 20%
- 20 题、10 分钟限时
- **非技术人员模板**
- PROMPT 50%、LLM 30%、WORK_CAPABILITY 20%
- 10 题,不含 IDE 和开发范式考核
- 维度名称用英文大写(PROMPT/LLM/IDE/DEV_PATTERN/WORK_CAPABILITY
- 权重是整数,总和不必为 100(系统会自动归一化)
### 8.4 组织考试
**管理员操作:**
1. 系统设置 → 用户管理 → 创建考生账号
2. 告知考生用户名密码
**考生操作:**
1. 登录系统 → 进入考核评估
2. 选择考核模板 → 开始专业评估
3. 答题(选择题点击选项→确认答案;简答题输入文字→发送)
4. AI 可能追问——继续作答
5. 完成后查看成绩
**查看结果:**
- 考核页面右侧「历史记录」栏显示所有历史成绩
- 点击记录查看每题得分、AI 评语
- 「查看证书」显示等级、总分、各维度得分
- 「下载 PDF 报告」「导出 Excel」
### 8.5 租户管理(仅 SUPER_ADMIN
```
系统设置 → 租户管理
```
- 创建租户 → 添加成员 → 分配角色
- 支持父子层级(父租户管理员可访问子租户)
- 数据严格隔离
---
## 九、配置参考
### 端口表
| 服务 | 端口 |
|---|---|
| 前端(开发) | 13001 |
| 后端 API | 3001 |
| Elasticsearch | 9200 |
| Apache Tika | 9998 |
| LibreOffice | 8100 |
| 前端(生产/Nginx | 80/443 |
### 环境变量(`server/.env`
```
PORT=3001 # 后端端口
DATABASE_PATH=./data/metadata.db # SQLite 路径
ELASTICSEARCH_HOST=http://127.0.0.1:9200
JWT_SECRET=<必填> # JWT 签名密钥
UPLOAD_FILE_PATH=./uploads # 文件存储
MAX_FILE_SIZE=104857600 # 上传限制
```
---
## 十、数据库操作
```bash
# 直接查询 SQLite
cd /d/AuraK && node -e "
const s = require('better-sqlite3');
const d = new s('server/data/metadata.db');
const r = d.prepare('SELECT * FROM users').all();
console.log(r);
d.close();
"
# TypeORM 自动建表(synchronize: true
# 重置数据库:删除 metadata.db 文件后重启即可
```
---
## 附录:架构图
```
┌────────────────────────────────────────────────────────────────┐
│ 前端 (Vite :13001) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ AuthCtx │ │ Pages │ │ Views │ │ Services │ │
│ │ 登录/租户 │ │ 路由页 │ │ 设置/考核 │ │ API 客户端 │ │
│ └──────────┘ └──────────┘ └──────────┘ └───────────────────┘ │
└──────────────────────────┬─────────────────────────────────────┘
│ HTTP / SSE
┌──────────────────────────▼─────────────────────────────────────┐
│ 后端 (NestJS :3001) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ Auth │ │ RBAC │ │ Assessment│ │ Knowledge Base │ │
│ │ JWT/Key │ │ 26 Perms │ │ Templates │ │ Tika/Vision/ES │ │
│ └──────────┘ └──────────┘ └──────────┘ └───────────────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ Tenant │ │ User │ │ Admin │ │ Super Admin │ │
│ │ 租户隔离 │ │ CRUD │ │ 管理端 │ │ 全局管理 │ │
│ └──────────┘ └──────────┘ └──────────┘ └───────────────────┘ │
└────────────────────────────────────────────────────────────────┘