# 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(...) { ... } // 前端——组件级门控 // 前端——条件渲染 const { hasPermission } = usePermissions(); {hasPermission('user:delete') && } ``` ### 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 ) → 返回 kb_xxxxxxxx...(前端存 localStorage) 后续请求: Headers: { x-api-key: , x-tenant-id: } ``` ### 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 │ │ 管理端 │ │ 全局管理 │ │ │ └──────────┘ └──────────┘ └──────────┘ └───────────────────┘ │ └────────────────────────────────────────────────────────────────┘