ebb8fbd298
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>
18 KiB
18 KiB
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)
快速命令
# 启动
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 实体模型
// 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 权限装饰器用法
// 后端——标记路由需要的权限(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 数据模型
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)
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-keyheader 或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:
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 可用:
await page.waitForFunction(() => {
const btn = document.querySelector('button:has(svg.lucide-send)');
return btn && !btn.disabled;
}, { timeout: 10000 });
等待 spinner 消失:
await page.waitForFunction(() => !document.querySelector('.animate-spin'), { timeout: 60000 });
检测考核题型:
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 组织考试
管理员操作:
- 系统设置 → 用户管理 → 创建考生账号
- 告知考生用户名密码
考生操作:
- 登录系统 → 进入考核评估
- 选择考核模板 → 开始专业评估
- 答题(选择题点击选项→确认答案;简答题输入文字→发送)
- AI 可能追问——继续作答
- 完成后查看成绩
查看结果:
- 考核页面右侧「历史记录」栏显示所有历史成绩
- 点击记录查看每题得分、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 # 上传限制
十、数据库操作
# 直接查询 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 │ │ 管理端 │ │ 全局管理 │ │
│ └──────────┘ └──────────┘ └──────────┘ └───────────────────┘ │
└────────────────────────────────────────────────────────────────┘