feat(admin): Add user management and upgrade to module permission system

Features - User Management (Phase 4.1):
- Database: Add user_modules table for fine-grained module permissions
- Database: Add 4 user permissions (view/create/edit/delete) to role_permissions
- Backend: UserService (780 lines) - CRUD with tenant isolation
- Backend: UserController + UserRoutes (648 lines) - 13 API endpoints
- Backend: Batch import users from Excel
- Frontend: UserListPage (412 lines) - list/filter/search/pagination
- Frontend: UserFormPage (341 lines) - create/edit with module config
- Frontend: UserDetailPage (393 lines) - details/tenant/module management
- Frontend: 3 modal components (592 lines) - import/assign/configure
- API: GET/POST/PUT/DELETE /api/admin/users/* endpoints

Architecture Upgrade - Module Permission System:
- Backend: Add getUserModules() method in auth.service
- Backend: Login API returns modules array in user object
- Frontend: AuthContext adds hasModule() method
- Frontend: Navigation filters modules based on user.modules
- Frontend: RouteGuard checks requiredModule instead of requiredVersion
- Frontend: Remove deprecated version-based permission system
- UX: Only show accessible modules in navigation (clean UI)
- UX: Smart redirect after login (avoid 403 for regular users)

Fixes:
- Fix UTF-8 encoding corruption in ~100 docs files
- Fix pageSize type conversion in userService (String to Number)
- Fix authUser undefined error in TopNavigation
- Fix login redirect logic with role-based access check
- Update Git commit guidelines v1.2 with UTF-8 safety rules

Database Changes:
- CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled)
- ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code)
- INSERT 4 permissions + role assignments
- UPDATE PUBLIC tenant with 8 module subscriptions

Technical:
- Backend: 5 new files (~2400 lines)
- Frontend: 10 new files (~2500 lines)
- Docs: 1 development record + 2 status updates + 1 guideline update
- Total: ~4900 lines of code

Status: User management 100% complete, module permission system operational
This commit is contained in:
2026-01-16 13:42:10 +08:00
parent 98d862dbd4
commit 66255368b7
560 changed files with 70424 additions and 52353 deletions

View File

@@ -1,45 +1,45 @@
# <EFBFBD>唳旿摨栞挽霈∟<EFBFBD><EFBFBD>?
# 数据库设计规范
> **<EFBFBD><EFBFBD>𧋦嚗?* v2.0
> **版本:** v2.0
> **最后更新:** 2025-11-06
> **数据库:** PostgreSQL 15+
> **ORM嚗?* Prisma
> **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>凒嚗?* 撟喳蝱撅?+ <20><EFBFBD>撅?+ 銝𡁜𦛚璅<E79285>撅?
> **ORM** Prisma
> **适用范围:** 平台层 + 能力层 + 业务模块层
---
## 📋 核心原则
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㗇芋<EFBFBD>埈㺭<EFBFBD><EFBFBD>霈曇恣<EFBFBD><EFBFBD>抅蝖<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>憿颱艇<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
本规范是所有模块数据库设计的基础规范,必须严格遵守。
**霈曇恣<EFBFBD><EFBFBD>嚗?*
- <EFBFBD>?<3F>萄儐蝚砌<E89D9A><E7A08C><EFBFBD><EFBFBD>嚗?NF嚗?
- <EFBFBD>?雿輻鍂SERIAL雿靝蛹銝駁睸嚗<EFBFBD><EFBFBD>啗䌊憓痹<EFBFBD><EFBFBD><EFBFBD><EFBFBD>游末嚗?
- <EFBFBD>?<3F><><EFBFBD>㕑”<E39591><E2809D>created_at<EFBFBD>pdated_at<EFBFBD>園𡢿<EFBFBD>?
- <EFBFBD>?<3F><EFBFBD>銵其蝙<E585B6>刻蔓<E588BB>𣳇膄嚗<E88684><E59A97><EFBFBD>eleted_at摮埈挾嚗?
- <EFBFBD>?憭㚚睸蝥行<E89DA5>雿輻鍂ON DELETE CASCADE
- <EFBFBD>?<3F>𤩺<EFBFBD>摮埈挾<E59F88><EFBFBD>摮睃<E691AE><EFBFBD><E59A97><EFBFBD><EFBFBD><EFBFBD>crypt嚗?
**设计原则:**
- ✅ 遵循第三范式3NF
- ✅ 使用SERIAL作为主键(整数自增,性能更好)
- ✅ 所有表包含created_at和updated_at时间戳
- ✅ 重要表使用软删除保留deleted_at字段)
- ✅ 外键约束使用ON DELETE CASCADE
- ✅ 敏感字段加密存储密码使用bcrypt
---
## <EFBFBD><EFBFBD>儭?Schema<EFBFBD>𠉛氖蝑𣇉裦 潃?<3F><><EFBFBD><EFBFBD>
## 🏗️ Schema隔离策略 ⭐ 最重要
### 为什么需要Schema隔离
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?*
1. <EFBFBD>?**璅<E79285><E288AA><EFBFBD><E7A589>?*嚗𡁏<E59A97>銝芯<E98A9D><E88AAF>⊥芋<E28AA5><EFBFBD><E59F88><EFBFBD><E7A589><EFBFBD>chema
2. <EFBFBD>?**<2A><EFBFBD><E88880><EFBFBD><E7A589>函蔡**嚗𡁜虾隞亙<E99A9E><E4BA99>砍紡<E7A08D><EFBFBD>銝芣芋<E88AA3><EFBFBD><E39B96>唳旿
3. <EFBFBD>?**<2A><EFBFBD><E88880><EFBFBD><E7A589><EFBFBD><EFBFBD>?*嚗𡁜虾隞亙<E99A9E><E4BA99>砌漱隞䀹<E99A9E>銝芣芋<E88AA3>?
4. <EFBFBD>?**<2A><><EFBFBD><EFBFBD>𠉛氖**嚗𡁜虾隞乩蛹銝滚<E98A9D>Schema霈曄蔭銝滚<E98A9D><E6BB9A><EFBFBD><EFBFBD>
5. <EFBFBD>?**<2A><EFBFBD><E8B8B9><EFBFBD><E8B3A2><EFBFBD>**嚗帋<E59A97><E5B88B>峕芋<E5B395>堒虾隞交<E99A9E><E4BAA4><EFBFBD><E8A9A8><EFBFBD><EFBFBD>?
**核心原因:**
1. **模块独立性**每个业务模块有独立的Schema
2. **支持独立部署**:可以单独导出某个模块的数据
3. **支持独立销售**:可以单独交付某个模块
4. **权限隔离**可以为不同Schema设置不同权限
5. **避免命名冲突**:不同模块可以有相同的表名
### Schema命名规范
```
platform_schema # 撟喳蝱<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>曹澈嚗?
platform_schema # 平台基础层(全局共享)
aia_schema # AI智能问答
asl_schema # AI智能文献
pkb_schema # 銝芯犖<EFBFBD><EFBFBD>摨?
pkb_schema # 个人知识库
dc_schema # 数据清洗整理
ssa_schema # 智能统计分析
st_schema # 统计分析工具
@@ -56,18 +56,18 @@ CREATE SCHEMA IF NOT EXISTS aia_schema;
-- ...其他Schema
```
### 頝沒chema靘肽<EFBFBD><EFBFBD><EFBFBD> 潃?敹<><EFBFBD><EFBFBD>
### 跨Schema依赖规则 ⭐ 必须遵守
**允许的依赖:**
```sql
-- <EFBFBD>?<3F><>捂嚗帋<E59A97><E5B88B>⊥芋<E28AA5><EFBFBD><E5A092>latform_schema
-- ✅ 允许业务模块引用platform_schema
CREATE TABLE asl_schema.literature_projects (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES platform_schema.users(id) ON DELETE CASCADE,
...
);
-- <EFBFBD>?<3F><>捂嚗𡁻<E59A97>𡁶鍂<F0A181B6><EFBFBD>撘閧鍂platform_schema
-- ✅ 允许:通用能力引用platform_schema
CREATE TABLE platform_schema.llm_usage (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES platform_schema.users(id) ON DELETE CASCADE,
@@ -77,14 +77,14 @@ CREATE TABLE platform_schema.llm_usage (
**禁止的依赖:**
```sql
-- <EFBFBD>?蝳<>迫嚗帋<E59A97><E5B88B>⊥芋<E28AA5>𦯀<EFBFBD><F0A6AF80><EFBFBD><E6B8AF><EFBFBD><E8A9A8>?
-- ❌ 禁止:业务模块之间互相引用
CREATE TABLE ssa_schema.analysis_projects (
id SERIAL PRIMARY KEY,
-- <EFBFBD>躰秤嚗<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞碶<EFBFBD><EFBFBD>⊥芋<EFBFBD>?
-- 错误!不能引用其他业务模块
literature_project_id INTEGER REFERENCES asl_schema.literature_projects(id)
);
-- <EFBFBD>?蝳<>迫嚗䮝latform_schema<EFBFBD><EFBFBD>靘肽<EFBFBD>銝𡁜𦛚璅<EFBFBD>
-- ❌ 禁止platform_schema反向依赖业务模块
CREATE TABLE platform_schema.users (
id SERIAL PRIMARY KEY,
-- 错误platform_schema不能依赖业务模块
@@ -92,104 +92,104 @@ CREATE TABLE platform_schema.users (
);
```
**<EFBFBD><EFBFBD>𡁏<EFBFBD>嚗?*
**正确做法:**
```
頝冽芋<EFBFBD>埈㺭<EFBFBD><EFBFBD><EFBFBD>𥪜銁摨𠉛鍂撅<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>銝滚銁<EFBFBD>唳旿摨枏<EFBFBD>嚗?
跨模块数据关联在应用层处理,不在数据库层!
方式1通过user_id关联
- 两个模块都引用platform_schema.users
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>user_id<EFBFBD>亥砭銝支葵璅<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
- 在应用层通过user_id查询两个模块的数据
- 在应用层组装数据
<EFBFBD><EFBFBD>2嚗𡁜<EFBFBD><EFBFBD><EFBFBD><EFBFBD>D摮㛖泵銝?
- <EFBFBD>刻”銝剖<EFBFBD><EFBFBD><EFBFBD>隞𡝗芋<EFBFBD><EFBFBD>銝𡁜𦛚ID嚗ĀARCHAR嚗?
- 銝滚遣蝡见<EFBFBD><EFBFBD><EFBFBD>蝟?
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD>撉諹<EFBFBD>ID<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
方式2存储业务ID字符串
- 在表中存储其他模块的业务IDVARCHAR
- 不建立外键关系
- 在应用层验证ID的有效性
```
---
## 📝 命名规范
### 銵典𦶢<EFBFBD>?
### 表命名
**<EFBFBD><EFBFBD>嚗?*
**规则:**
- 小写字母
- 銝见<EFBFBD>蝥踹<EFBFBD><EFBFBD>?
- 下划线分隔
- 复数形式
- Schema<EFBFBD><EFBFBD><EFBFBD>䰻霂𧒄雿輻鍂嚗?
- Schema前缀(查询时使用)
**蝷箔<EFBFBD>嚗?*
**示例:**
```sql
-- <EFBFBD>?甇<>
-- ✅ 正确
CREATE TABLE asl_schema.literature_projects (...);
CREATE TABLE platform_schema.users (...);
CREATE TABLE pkb_schema.knowledge_bases (...);
-- <EFBFBD>?<3F>躰秤
-- ❌ 错误
CREATE TABLE ASLSchema.LiteratureProject (...); -- 驼峰
CREATE TABLE asl_schema.project (...); -- 单数
CREATE TABLE literature-projects (...); -- 雿輻鍂餈𧼮<EFBFBD>蝚?
CREATE TABLE literature-projects (...); -- 使用连字符
```
### 字段命名
**<EFBFBD><EFBFBD>嚗?*
**规则:**
- 小写字母
- 銝见<EFBFBD>蝥踹<EFBFBD><EFBFBD>?
- 下划线分隔
- 语义清晰
**蝷箔<EFBFBD>嚗?*
**示例:**
```sql
-- <EFBFBD>?甇<>
-- ✅ 正确
user_id
created_at
project_name
is_active
-- <EFBFBD>?<3F>躰秤
-- ❌ 错误
userId -- 驼峰
createdat -- 瘝⊥<EFBFBD>銝见<EFBFBD>蝥?
prjName -- 蝻拙<EFBFBD>銝齿<EFBFBD><EFBFBD>?
createdat -- 没有下划线
prjName -- 缩写不清晰
```
### 索引命名
**<EFBFBD><EFBFBD>嚗?* `idx_銵典<E98AB5>_摮埈挾<E59F88>
**规则:** `idx_表名_字段名`
**蝷箔<EFBFBD>嚗?*
**示例:**
```sql
-- <20>?甇<>
-- ✅ 正确
CREATE INDEX idx_users_email ON platform_schema.users(email);
CREATE INDEX idx_projects_user_id ON asl_schema.literature_projects(user_id);
CREATE INDEX idx_projects_user_status ON asl_schema.literature_projects(user_id, status);
-- <20>?<3F>躰秤
-- ❌ 错误
CREATE INDEX user_email_idx ... -- 顺序错误
CREATE INDEX index_on_email ... -- <EFBFBD>滨妍銝齿<EFBFBD><EFBFBD>?
CREATE INDEX index_on_email ... -- 名称不清晰
```
### 外键命名
**<EFBFBD><EFBFBD>嚗?* `fk_銵典<EFBFBD>_<EFBFBD><EFBFBD>銵典<EFBFBD>`
**规则:** `fk_表名_关联表名`
**蝷箔<EFBFBD>嚗?*
**示例:**
```sql
-- <20>?甇<>
-- ✅ 正确
CONSTRAINT fk_projects_users
FOREIGN KEY (user_id) REFERENCES platform_schema.users(id);
CONSTRAINT fk_items_projects
FOREIGN KEY (project_id) REFERENCES asl_schema.literature_projects(id);
-- <20>?<3F>躰秤
CONSTRAINT user_fk ... -- <EFBFBD>滨妍銝齿<EFBFBD><EFBFBD>?
-- ❌ 错误
CONSTRAINT user_fk ... -- 名称不清晰
CONSTRAINT foreign_key_users ... -- 太长
```
---
## <EFBFBD><EFBFBD> <20>𡁶鍂摮埈挾 潃?敹<><EFBFBD><E29786>
## 📊 通用字段 ⭐ 必须包含
### 所有表必须包含
@@ -201,13 +201,13 @@ CREATE TABLE xxx_schema.table_name (
-- 业务字段
...
-- <EFBFBD>園𡢿<EFBFBD><EFBFBD><EFBFBD>◆嚗?
-- 时间戳(必须)
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP DEFAULT NOW() NOT NULL
);
```
### <EFBFBD><EFBFBD>銵典<EFBFBD><EFBFBD><EFBFBD>鉄嚗<EFBFBD><EFBFBD>𣳇膄嚗?
### 重要表应包含(软删除)
```sql
CREATE TABLE xxx_schema.important_table (
@@ -219,7 +219,7 @@ CREATE TABLE xxx_schema.important_table (
-- 软删除字段(可选,重要表建议添加)
deleted_at TIMESTAMP,
-- <EFBFBD>園𡢿<EFBFBD><EFBFBD><EFBFBD>◆嚗?
-- 时间戳(必须)
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP DEFAULT NOW() NOT NULL
);
@@ -228,7 +228,7 @@ CREATE TABLE xxx_schema.important_table (
SELECT * FROM xxx_schema.important_table WHERE deleted_at IS NULL;
```
### <EFBFBD><EFBFBD><EFBFBD><EFBFBD>銵典<EFBFBD>憿餃<EFBFBD><EFBFBD>?
### 用户关联表必须包含
```sql
CREATE TABLE xxx_schema.user_related_table (
@@ -240,7 +240,7 @@ CREATE TABLE xxx_schema.user_related_table (
-- 业务字段
...
-- <EFBFBD>園𡢿<EFBFBD><EFBFBD><EFBFBD>◆嚗?
-- 时间戳(必须)
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP DEFAULT NOW() NOT NULL
);
@@ -250,7 +250,7 @@ CREATE TABLE xxx_schema.user_related_table (
## 🔍 索引设计规范
### <EFBFBD>◆瘛餃<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>畾?
### 必须添加索引的字段
**1. 主键**
```sql
@@ -266,7 +266,7 @@ CREATE INDEX idx_projects_user_id ON asl_schema.literature_projects(user_id);
**3. 常用查询字段**
```sql
-- status<EFBFBD>𠶖<EFBFBD><EFBFBD><EFBFBD>畾蛛<EFBFBD>撣貊鍂鈭竝HERE嚗?
-- status状态字段常用于WHERE
CREATE INDEX idx_projects_status ON asl_schema.literature_projects(status);
-- created_at时间字段常用于排序
@@ -281,22 +281,22 @@ CREATE UNIQUE INDEX idx_users_email ON platform_schema.users(email);
### 复合索引
**<EFBFBD><EFBFBD>嚗?*
**规则:**
- 高频组合查询使用复合索引
- 最常查询的字段放在前面
- 憭滚<E686AD><E89D9D><EFBCB7><EFBFBD>憭?銝芸<E98A9D>畾?
- 复合索引最多3个字段
**蝷箔<EFBFBD>嚗?*
**示例:**
```sql
-- <20>?甇<>嚗鮁ser_id + status <EFBFBD><EFBFBD><EFBFBD>亥砭
-- ✅ 正确user_id + status 组合查询
CREATE INDEX idx_projects_user_status
ON asl_schema.literature_projects(user_id, status);
-- <20>臭誑隡睃<E99AA1>隞乩<E99A9E><E4B9A9>亥砭嚗?
-- 可以优化以下查询:
-- WHERE user_id = ? AND status = ?
-- WHERE user_id = ? <EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?
-- WHERE user_id = ? (只用前缀)
-- <20>?<3F>躰秤嚗𡁜<E59A97>畾菔<E795BE>憭?
-- ❌ 错误:字段过多
CREATE INDEX idx_projects_complex
ON asl_schema.literature_projects(user_id, status, created_at, updated_at);
```
@@ -307,7 +307,7 @@ CREATE INDEX idx_projects_complex
### ON DELETE策略
**<EFBFBD><EFBFBD>嚗?*
**规则:**
```sql
-- 用户删除时,级联删除关联数据
FOREIGN KEY (user_id)
@@ -319,15 +319,15 @@ FOREIGN KEY (project_id)
REFERENCES asl_schema.literature_projects(id)
ON DELETE CASCADE;
-- <20><EFBFBD><E5AF9E><EFBFBD><EFBFBD>嚗帋<E59A97><E5B88B><EFBFBD><E8B3A2>?
-- 特殊情况:不能删除
FOREIGN KEY (parent_id)
REFERENCES xxx_schema.parent_table(id)
ON DELETE RESTRICT; -- <20><EFBFBD>霈啣<E99C88><E595A3><EFBFBD><E79487><EFBCB7>?
ON DELETE RESTRICT; -- 有子记录时禁止删除
```
### 外键索引
**<EFBFBD><EFBFBD>嚗?* <20><><EFBFBD><EFBFBD><E58CA7><EFBFBD>憿餅溶<E9A485>删揣撘?
**规则:** 所有外键必须添加索引
```sql
-- 创建外键
@@ -342,11 +342,11 @@ CREATE INDEX idx_items_project_id ON asl_schema.literature_items(project_id);
---
## <EFBFBD>?<3F><EFBFBD>隡睃<E99AA1><EFBFBD><E996AB>
## ⚡ 性能优化规范
### 大表分区(可选)
**<2A><><EFBFBD>箸艶嚗?* 撟游<E6929F><E6B8B8>?> 100銝<30>扇敶?
**适用场景:** 年增长 > 100万记录
```sql
-- 按月分区如llm_usage表
@@ -388,13 +388,13 @@ WHERE created_at < NOW() - INTERVAL '1 year';
```sql
-- 密码字段
password VARCHAR(255) NOT NULL -- 雿輻鍂bcrypt<70><EFBFBD><EFBFBD><E59A97><EFBFBD><EFBFBD><EFBFBD><E692A3>?
password VARCHAR(255) NOT NULL -- 使用bcrypt加密存储哈希值
-- API Key字段
api_key_encrypted TEXT NOT NULL -- 使用AES-256加密
-- 个人敏感信息
phone_encrypted VARCHAR(255) -- <EFBFBD>𧢲㦤<EFBFBD><EFBFBD>撖?
phone_encrypted VARCHAR(255) -- 手机号加密
id_card_encrypted VARCHAR(255) -- 身份证号加密
```
@@ -402,7 +402,7 @@ id_card_encrypted VARCHAR(255) -- 身份证号加密
```sql
-- 日志中不记录敏感字段
-- 撘<><E69298>?瘚贝<E7989A><E8B49D><EFBFBD>雿輻鍂<E8BCBB><EFBFBD><E69C9B>唳旿
-- 开发/测试环境使用脱敏数据
UPDATE platform_schema.users
SET
email = CONCAT('user', id, '@example.com'),
@@ -416,71 +416,71 @@ WHERE environment = 'development';
### 常用字段类型
| <EFBFBD><EFBFBD>?| <20><EFBFBD>蝐餃<E89D90> | 霂湔<E99C82> |
| 用途 | 推荐类型 | 说明 |
|------|---------|------|
| 主键 | SERIAL | 整数自增 |
| 憭㚚睸 | INTEGER | 銝𦒘蜓<EFBFBD>桃掩<EFBFBD><EFBFBD><EFBFBD>?|
| <EFBFBD><EFBFBD><EFBFBD>?| VARCHAR(N) | N<500<EFBFBD><EFBFBD>憪枏<EFBFBD><EFBFBD><EFBFBD><EFBFBD>憸?|
| <EFBFBD><EFBFBD><EFBFBD>?| TEXT | <EFBFBD>𣳇鵭摨阡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>餈啜<EFBFBD><EFBFBD><EFBFBD>摰?|
| <EFBFBD><EFBFBD><EFBFBD>?| BOOLEAN | true/false |
| <EFBFBD><EFBFBD><EFBFBD>園𡢿 | TIMESTAMP | 蝎曄<EFBFBD>唳神蝘?|
| 外键 | INTEGER | 与主键类型一致 |
| 短文本 | VARCHAR(N) | N<500,如姓名、标题 |
| 长文本 | TEXT | 无长度限制,如描述、内容 |
| 布尔值 | BOOLEAN | true/false |
| 日期时间 | TIMESTAMP | 精确到毫秒 |
| 金额 | DECIMAL(10,2) | 避免精度问题 |
| JSON | JSONB | 支持索引,性能更好 |
### 字段长度建议
```sql
-- <20><EFBFBD><E5899C>?
-- 短文本
name VARCHAR(100) -- 姓名
title VARCHAR(200) -- 标题
email VARCHAR(255) -- 邮箱
phone VARCHAR(20) -- <EFBFBD>𧢲㦤<EFBFBD>?
phone VARCHAR(20) -- 手机号
-- <20><EFBFBD><E59786><EFBFBD>銝?
-- 状态枚举
status VARCHAR(20) -- active, inactive, deleted
role VARCHAR(20) -- user, admin
-- <20><EFBFBD><E8B8B5>?
-- 长文本
description TEXT -- 描述
content TEXT -- 内容
```
---
## <EFBFBD>?璉<><E79289><EFBFBD><E4BAA4>?
## ✅ 检查清单
**设计新表时必须检查:**
- [ ] 銵典<EFBFBD>蝚血<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?銝见<E98A9D>蝥?憭齿㺭嚗?
- [ ] 表名符合命名规范(小写+下划线+复数)
- [ ] 使用正确的Schemaplatform/aia/asl/pkb等
- [ ] <EFBFBD><EFBFBD>鉄id銝駁睸嚗𠄎ERIAL PRIMARY KEY嚗?
- [ ] <EFBFBD><EFBFBD>created_at<EFBFBD>pdated_at<EFBFBD>園𡢿<EFBFBD>?
- [ ] 包含id主键SERIAL PRIMARY KEY
- [ ] 包含created_at和updated_at时间戳
- [ ] 用户关联表包含user_id外键
- [ ] 所有外键都有ON DELETE策略
- [ ] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>瘛餃<EFBFBD><EFBFBD>揣撘?
- [ ] 撣貊鍂<EFBFBD>亥砭摮埈挾瘛餃<EFBFBD><EFBFBD>揣撘?
- [ ] 所有外键都添加了索引
- [ ] 常用查询字段添加了索引
- [ ] 外键约束符合跨Schema依赖规则
- [ ] <EFBFBD>𤩺<EFBFBD>摮埈挾撌脣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
- [ ] 敏感字段已加密存储
---
## 🔗 相关文档
**<EFBFBD><EFBFBD>嚗?*
- [<EFBFBD>唳旿摨枏<EFBFBD><EFBFBD><EFBFBD>](./03-<2D>唳旿摨枏<E691A8><EFBFBD><EFBFBD>㦛.md) 潃?<3F><EFBFBD><E4BAA6><EFBFBD><EFBFBD>chema<EFBFBD>諹”
**总览:**
- [数据库全局视图](./03-数据库全局视图.md) ⭐ 查看所有Schema和表
**璅⊥踎嚗?*
- [<EFBFBD>唳旿摨栞挽霈⊥芋<EFBFBD>瓢(../_templates/<EFBFBD>唳旿摨栞挽霈?璅⊥踎.md)
**模板:**
- [数据库设计模板](../_templates/数据库设计-模板.md)
**各模块设计:**
- [撟喳蝱<EFBFBD><EFBFBD><EFBFBD>(../01-撟喳蝱<E596B3><EFBFBD>撅?README.md)
- [<EFBFBD>𡁶鍂<EFBFBD><EFBFBD><EFBFBD>(../02-<2D>𡁶鍂<F0A181B6><EFBFBD>撅?README.md)
- [平台基础层](../01-平台基础层/README.md)
- [通用能力层](../02-通用能力层/README.md)
- [业务模块层](../03-业务模块/README.md)
---
**最后更新:** 2025-11-06
**维护人:** 技术架构师
**<EFBFBD><EFBFBD>𧋦嚗?* v2.0
**版本:** v2.0

View File

@@ -1,32 +1,32 @@
# API设计规范
> **<EFBFBD><EFBFBD>𧋦嚗?* v2.0
> **版本:** v2.0
> **最后更新:** 2025-11-06
> **API憌擧聢嚗?* RESTful API
> **<EFBFBD><EFBFBD>URL嚗?* `http://localhost:3001/api/v1`
> **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>凒嚗?* 撟喳蝱撅?+ <20><EFBFBD>撅?+ 銝𡁜𦛚璅<E79285>撅?
> **API风格:** RESTful API
> **基础URL** `http://localhost:3001/api/v1`
> **适用范围:** 平台层 + 能力层 + 业务模块层
---
## 📋 设计原则
### API First原则
- <EFBFBD>?<3F><>挽霈PI嚗<49><E59A97>摰䂿緵<E482BF><EFBFBD>
- <EFBFBD>?API<EFBFBD><EFBFBD><EFBFBD>𡒊垢<EFBFBD><EFBFBD><EFBFBD>蝥?
- <EFBFBD>?API<EFBFBD>䀹凒<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>祆綉<EFBFBD>?
- <EFBFBD>?<3F><><EFBFBD>𡅅PI<50><EFBFBD><E8B3AA><EFBFBD>獢?
- ✅ 先设计API再实现功能
- API是前后端的契约
- API变更需要版本控制
- ✅ 所有API都要有文档
### RESTful设计
- <EFBFBD>?雿輻鍂HTTP<54><EFBFBD>銵函內<E587BD><EFBFBD>嚗𠃑ET<45><54>OST<53><54>UT<55><54>ELETE嚗?
- <EFBFBD>?URL銵函內韏<EFBFBD><EFBFBD>嚗䔶<EFBFBD>銵函內<EFBFBD><EFBFBD>
- <EFBFBD>?雿輻鍂憭齿㺭<E9BDBF><EFBFBD>銵函內韏<E585A7><E99F8F><EFBFBD><EFBFBD><EFBFBD>
- <EFBFBD>?撋<><E6928B><EFBFBD><E99F8F>銝滩<E98A9D>餈?撅?
- <EFBFBD>?雿輻鍂HTTP<54><EFBFBD><E59786><EFBFBD>銵函內蝏𤘪<E89D8F>
- ✅ 使用HTTP动词表示操作GET、POST、PUT、DELETE
- URL表示资源,不表示动作
- ✅ 使用复数名词表示资源集合
- ✅ 嵌套资源不超过2层
- ✅ 使用HTTP状态码表示结果
### 命名规范
- <EFBFBD>?URL雿輻鍂撠誩<EFBFBD>摮埈<EFBFBD><EFBFBD><EFBFBD>摮㛖泵嚗ɑebab-case嚗?
- <EFBFBD>?<3F>亥砭<E4BAA5><E7A0AD>㺭雿輻鍂撽澆陸<E6BE86><EFBFBD>嚗ẾamelCase嚗?
- <EFBFBD>?JSON摮埈挾雿輻鍂撽澆陸<EFBFBD><EFBFBD>嚗ẾamelCase嚗?
- URL使用小写字母和连字符kebab-case
- ✅ 查询参数使用驼峰命名camelCase
- JSON字段使用驼峰命名camelCase
---
@@ -37,9 +37,9 @@
```
/api/v{version}/{module}/{resource}/{id?}/{action?}
蝷箔<EFBFBD>嚗?
示例:
/api/v1/literature/projects # 获取文献项目列表
/api/v1/literature/projects/123 # <EFBFBD><EFBFBD>ID=123<EFBFBD><EFBFBD><EFBFBD>?
/api/v1/literature/projects/123 # 获取ID=123的项目
/api/v1/literature/projects/123/export # 导出项目(动作)
```
@@ -50,19 +50,19 @@
| 认证 | `/auth` | `/api/v1/auth/login` |
| 用户 | `/users` | `/api/v1/users/me` |
| AI问答 | `/chat` | `/api/v1/chat/conversations` |
| <EFBFBD><EFBFBD>雿?| `/agents` | `/api/v1/agents` |
| 智能体 | `/agents` | `/api/v1/agents` |
| AI文献 | `/literature` | `/api/v1/literature/projects` |
| <EFBFBD><EFBFBD>摨?| `/knowledge-bases` | `/api/v1/knowledge-bases` |
| 知识库 | `/knowledge-bases` | `/api/v1/knowledge-bases` |
| 数据清洗 | `/data-cleaning` | `/api/v1/data-cleaning/projects` |
| 统计分析 | `/analysis` | `/api/v1/analysis/projects` |
| 统计工具 | `/tools` | `/api/v1/tools` |
| 稿件审查 | `/review` | `/api/v1/review/tasks` |
| LLM网关 | `/llm` | `/api/v1/llm/chat` |
| 蝞∠<EFBFBD>蝡?| `/admin` | `/api/v1/admin/users` |
| 管理端 | `/admin` | `/api/v1/admin/users` |
### 资源命名
**<EFBFBD>?甇<>蝷箔<E89DB7>嚗?*
**✅ 正确示例:**
```
GET /api/v1/literature/projects # 获取列表
GET /api/v1/literature/projects/:id # 获取详情
@@ -72,10 +72,10 @@ DELETE /api/v1/literature/projects/:id # 删除
GET /api/v1/literature/projects/:id/items # 获取项目下的文献
POST /api/v1/literature/projects/:id/items/import # 导入文献
POST /api/v1/literature/projects/:id/screening/execute # <EFBFBD><EFBFBD>蝑偦<EFBFBD>?
POST /api/v1/literature/projects/:id/screening/execute # 执行筛选
```
**<EFBFBD>?<3F>躰秤蝷箔<E89DB7>嚗?*
**❌ 错误示例:**
```
POST /api/v1/literature/getProjects # 使用动词
POST /api/v1/literature/createProject # 使用动词
@@ -89,13 +89,13 @@ GET /api/v1/literatureProjectList # 驼峰命名
### 方法使用
| <EFBFBD><EFBFBD> | <20><EFBFBD>?| <20>臬炏撟<E7828F><E6929F> | <20>臬炏摰匧<E691B0> |
| 方法 | 用途 | 是否幂等 | 是否安全 |
|------|------|---------|---------|
| **GET** | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20>?| <20>?|
| **POST** | <EFBFBD>𥕦遣韏<EFBFBD><EFBFBD> | <20>?| <20>?|
| **PUT** | 摰峕㟲<EFBFBD>湔鰵韏<EFBFBD><EFBFBD> | <20>?| <20>?|
| **PATCH** | <EFBFBD><EFBFBD><EFBFBD>湔鰵韏<EFBFBD><EFBFBD> | <20>?| <20>?|
| **DELETE** | <EFBFBD>𣳇膄韏<EFBFBD><EFBFBD> | <20>?| <20>?|
| **GET** | 获取资源 | ✅ | ✅ |
| **POST** | 创建资源 | ❌ | ❌ |
| **PUT** | 完整更新资源 | ✅ | ❌ |
| **PATCH** | 部分更新资源 | ❌ | ❌ |
| **DELETE** | 删除资源 | ✅ | ❌ |
### 方法示例
@@ -109,7 +109,7 @@ GET /api/v1/literature/projects/123
#
POST /api/v1/literature/projects
Content-Type: application/json
{ "name": "<EFBFBD><EFBFBD>?, "description": "..." }
{ "name": "", "description": "..." }
#
PUT /api/v1/literature/projects/123
@@ -119,7 +119,7 @@ Content-Type: application/json
#
PATCH /api/v1/literature/projects/123
Content-Type: application/json
{ "name": "<EFBFBD><EFBFBD><EFBFBD>? }
{ "name": "" }
#
DELETE /api/v1/literature/projects/123
@@ -135,15 +135,15 @@ DELETE /api/v1/literature/projects/123
|--------|------|---------|
| **200** | OK | 成功返回数据 |
| **201** | Created | 成功创建资源 |
| **204** | No Content | <EFBFBD>𣂼<EFBFBD><EFBFBD><EFBFBD>餈𥪜<EFBFBD><EFBFBD>唳旿嚗<EFBFBD><EFBFBD><EFBFBD>𣳇膄嚗?|
| **204** | No Content | 成功但无返回数据(如删除) |
| **400** | Bad Request | 请求参数错误 |
| **401** | Unauthorized | <EFBFBD>芾恕霂<EFBFBD><EFBFBD>瘝⊥<EFBFBD>Token<EFBFBD>oken<EFBFBD><EFBFBD>嚗?|
| **403** | Forbidden | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>撌脰恕霂<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>銝滩雲嚗?|
| **404** | Not Found | <EFBFBD><EFBFBD>銝滚<EFBFBD><EFBFBD>?|
| **409** | Conflict | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>𥕦遣嚗?|
| **422** | Unprocessable Entity | 霂凋<EFBFBD><EFBFBD>躰秤嚗<EFBFBD><EFBFBD>撉諹<EFBFBD>憭梯揖嚗?|
| **401** | Unauthorized | 未认证(没有Token或Token过期) |
| **403** | Forbidden | 无权限(已认证但权限不足) |
| **404** | Not Found | 资源不存在 |
| **409** | Conflict | 资源冲突(如重复创建) |
| **422** | Unprocessable Entity | 语义错误(如验证失败) |
| **429** | Too Many Requests | 请求过于频繁(限流) |
| **500** | Internal Server Error | <EFBFBD>滚𦛚<EFBFBD><EFBFBD>霂?|
| **500** | Internal Server Error | 服务器错误 |
### 状态码使用示例
@@ -154,7 +154,7 @@ res.status(200).json({ success: true, data: projects });
// 201 Created - 成功创建资源
res.status(201).json({ success: true, data: newProject });
// 204 No Content - <EFBFBD>𣂼<EFBFBD><EFBFBD>𣳇膄嚗<EFBFBD><EFBFBD><EFBFBD><EFBFBD>捆餈𥪜<EFBFBD>嚗?
// 204 No Content - 成功删除(无内容返回)
res.status(204).send();
// 400 Bad Request - 参数错误
@@ -163,22 +163,22 @@ res.status(400).json({
error: { code: 'INVALID_PARAMS', message: '参数错误' }
});
// 401 Unauthorized - <EFBFBD>芾恕霂?
// 401 Unauthorized - 未认证
res.status(401).json({
success: false,
error: { code: 'UNAUTHORIZED', message: '请先登录' }
});
// 403 Forbidden - <EFBFBD><EFBFBD><EFBFBD>?
// 403 Forbidden - 无权限
res.status(403).json({
success: false,
error: { code: 'FORBIDDEN', message: '无权访问' }
});
// 404 Not Found - <EFBFBD><EFBFBD>銝滚<EFBFBD><EFBFBD>?
// 404 Not Found - 资源不存在
res.status(404).json({
success: false,
error: { code: 'NOT_FOUND', message: '<EFBFBD><EFBFBD>銝滚<EFBFBD><EFBFBD>? }
error: { code: 'NOT_FOUND', message: '资源不存在' }
});
// 422 Unprocessable Entity - 验证失败
@@ -196,9 +196,9 @@ res.status(422).json({
## 📝 响应格式规范
### 蝏煺<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 潃?敹<><EFBFBD><EFBFBD>
### 统一响应格式 ⭐ 必须遵守
**<EFBFBD>𣂼<EFBFBD><EFBFBD><EFBFBD>嚗?*
**成功响应:**
```json
{
"success": true,
@@ -209,7 +209,7 @@ res.status(422).json({
}
```
**<EFBFBD>躰秤<EFBFBD><EFBFBD>嚗?*
**错误响应:**
```json
{
"success": false,
@@ -255,11 +255,11 @@ res.status(422).json({
"details": [
{
"field": "email",
"message": "<EFBFBD>桃拳<EFBFBD><EFBFBD>銝齿迤蝖?
"message": "邮箱格式不正确"
},
{
"field": "password",
"message": "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>6?
"message": "密码长度必须大于6位"
}
]
}
@@ -268,7 +268,7 @@ res.status(422).json({
---
## <EFBFBD><EFBFBD> 霈方<E99C88>銝擧<E98A9D><E693A7><EFBFBD><EFBFBD><EFBFBD>?
## 🔑 认证与授权规范
### JWT认证
@@ -307,12 +307,12 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
**3. Token过期处理**
```http
# Token<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?01
# Token401
{
"success": false,
"error": {
"code": "TOKEN_EXPIRED",
"message": "Token<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
"message": "Token"
}
}
@@ -327,23 +327,23 @@ Content-Type: application/json
### 权限控制
| 蝡舐<EFBFBD>蝐餃<EFBFBD> | <20><><EFBFBD>恕霂?| 閫坿𠧧閬<F0A0A7A7><E996AC> |
| 端点类型 | 需要认证 | 角色要求 |
|---------|---------|---------|
| <EFBFBD><EFBFBD>蝡舐<EFBFBD> | <20>?| <20>?|
| <EFBFBD><EFBFBD>蝡舐<EFBFBD> | <EFBFBD>?| user |
| 蝞∠<EFBFBD>蝡舐<EFBFBD> | <EFBFBD>?| admin |
| 公开端点 | ❌ | 无 |
| 用户端点 | | user |
| 管理端点 | | admin |
**蝷箔<EFBFBD>嚗?*
**示例:**
```typescript
// <EFBFBD><EFBFBD>蝡舐<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>霈方<EFBFBD>嚗?
// 公开端点(无需认证)
POST /api/v1/auth/login
POST /api/v1/auth/register
// <EFBFBD><EFBFBD>蝡舐<EFBFBD><EFBFBD><EFBFBD><EFBFBD>恕霂<EFBFBD><EFBFBD>user閫坿𠧧嚗?
// 用户端点需要认证user角色
GET /api/v1/literature/projects
POST /api/v1/literature/projects
// 蝞∠<EFBFBD>蝡舐<EFBFBD><EFBFBD><EFBFBD><EFBFBD>恕霂<EFBFBD><EFBFBD>admin閫坿𠧧嚗?
// 管理端点需要认证admin角色
GET /api/v1/admin/users
POST /api/v1/admin/users/:id/disable
```
@@ -357,11 +357,11 @@ POST /api/v1/admin/users/:id/disable
```
GET /api/v1/literature/projects?page=1&pageSize=20&sortBy=createdAt&sortOrder=desc
Query<EFBFBD><EFBFBD>㺭嚗?
- page: 憿萇<EFBFBD><EFBFBD><EFBFBD>霈?嚗?
- pageSize: 瘥誯△<EFBFBD><EFBFBD><EFBFBD><EFBFBD>霈?0嚗峕<E59A97>憭?00嚗?
- sortBy: <EFBFBD><EFBFBD>摮埈挾嚗<EFBFBD><EFBFBD>霈勺reatedAt嚗?
- sortOrder: <EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗Òsc/desc嚗屸<EFBFBD>霈千esc嚗?
Query参数:
- page: 页码默认1
- pageSize: 每页数量默认10最大100
- sortBy: 排序字段默认createdAt
- sortOrder: 排序方向asc/desc默认desc
```
### 响应格式
@@ -387,16 +387,16 @@ Query参数
## 🔍 筛选与搜索规范
### 蝑偦<EFBFBD><EFBFBD><EFBFBD>?
### 筛选参数
```
GET /api/v1/literature/projects?status=active&keyword=骨质疏松
Query<EFBFBD><EFBFBD>㺭嚗?
- status: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>active/inactive嚗?
- keyword: <EFBFBD>喲睸霂齿<EFBFBD><EFBFBD><EFBFBD>𦦵揣name<EFBFBD>𩥇escription摮埈挾嚗?
Query参数:
- status: 状态筛选(active/inactive
- keyword: 关键词搜索(搜索name和description字段)
- userId: 用户ID筛选管理端
- startDate/endDate: <EFBFBD><EFBFBD><EFBFBD><EFBFBD>凒蝑偦<EFBFBD>?
- startDate/endDate: 日期范围筛选
```
### 搜索响应
@@ -417,29 +417,29 @@ Query参数
---
## <EFBFBD>𩤃<EFBFBD> <20>躰秤<E8BAB0><E7A7A4>挽霈?
## ⚠️ 错误码设计
### <EFBFBD><EFBFBD><EFBFBD><EFBFBD>躰秤<EFBFBD>?
### 标准错误码
| <EFBFBD>躰秤<EFBFBD>?| HTTP<EFBFBD><EFBFBD>?| 霂湔<E99C82> |
| 错误码 | HTTP状态 | 说明 |
|--------|---------|------|
| `VALIDATION_ERROR` | 422 | 参数验证失败 |
| `UNAUTHORIZED` | 401 | <EFBFBD>芾恕霂?|
| `UNAUTHORIZED` | 401 | 未认证 |
| `TOKEN_EXPIRED` | 401 | Token过期 |
| `FORBIDDEN` | 403 | <EFBFBD><EFBFBD><EFBFBD>?|
| `NOT_FOUND` | 404 | <EFBFBD><EFBFBD>銝滚<EFBFBD><EFBFBD>?|
| `ALREADY_EXISTS` | 409 | <EFBFBD><EFBFBD>撌脣<EFBFBD><EFBFBD>?|
| `FORBIDDEN` | 403 | 无权限 |
| `NOT_FOUND` | 404 | 资源不存在 |
| `ALREADY_EXISTS` | 409 | 资源已存在 |
| `QUOTA_EXCEEDED` | 429 | 配额超限 |
| `INTERNAL_ERROR` | 500 | <EFBFBD>滚𦛚<EFBFBD><EFBFBD>霂?|
| `INTERNAL_ERROR` | 500 | 服务器错误 |
### 銝𡁜𦛚<EFBFBD>躰秤<EFBFBD>?
### 业务错误码
```typescript
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>躰秤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?
ASL_IMPORT_FAILED // AI<EFBFBD><EFBFBD>讃嚗𡁜紡<EFBFBD>亙仃韐?
// 模块特定错误码(前缀区分)
ASL_IMPORT_FAILED // AI文献:导入失败
ASL_SCREENING_IN_PROGRESS // AI文献筛选进行中
PKB_QUOTA_EXCEEDED // 知识库:配额超限
LLM_QUOTA_EXCEEDED // LLM嚗𡁻<EFBFBD>憸肽<EFBFBD><EFBFBD>?
LLM_QUOTA_EXCEEDED // LLM:配额超限
```
---
@@ -452,7 +452,7 @@ LLM_QUOTA_EXCEEDED // LLM配额超
所有列表接口必须支持分页:
- 默认pageSize=10
- 最大pageSize=100
- <EFBFBD>迫銝<EFBFBD>甈⊥<EFBFBD><EFBFBD><EFBFBD>𧼮<EFBFBD><EFBFBD>冽㺭<EFBFBD>?
- 禁止一次性返回全部数据
```
### 2. 字段过滤
@@ -460,13 +460,13 @@ LLM_QUOTA_EXCEEDED // LLM配额超
```
GET /api/v1/users/me?fields=id,name,email
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>摮埈挾嚗<EFBFBD><EFBFBD>撠烐㺭<EFBFBD><EFBFBD>颲?
只返回需要的字段,减少数据传输
```
### 3. 缓存策略
```http
# <EFBFBD>?
#
Cache-Control: public, max-age=300
# 使ETag
@@ -477,40 +477,40 @@ If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
---
## <EFBFBD>?璉<><E79289><EFBFBD><E4BAA4>?
## ✅ 检查清单
**设计新API时必须检查**
- [ ] URL蝚血<EFBFBD>RESTful<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>霂?憭齿㺭嚗?
- [ ] 雿輻鍂甇<EFBFBD><EFBFBD><EFBFBD>TTP<EFBFBD><EFBFBD>嚗𠃑ET/POST/PUT/DELETE嚗?
- [ ] URL符合RESTful规范(使用名词+复数)
- [ ] 使用正确的HTTP方法GET/POST/PUT/DELETE
- [ ] 使用正确的HTTP状态码
- [ ] <EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝚血<EFBFBD>蝏煺<EFBFBD><EFBFBD><EFBFBD>嚗ìuccess + data/error嚗?
- [ ] 响应格式符合统一规范success + data/error
- [ ] 需要认证的接口检查JWT Token
- [ ] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>亙藁璉<EFBFBD><EFBFBD>亦鍂<EFBFBD><EFBFBD><EFBFBD>?
- [ ] 需要权限的接口检查用户角色
- [ ] 列表接口支持分页
- [ ] 列表接口支持排序
- [ ] <EFBFBD>躰秤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>𡒊<EFBFBD><EFBFBD><EFBFBD>霂舐<EFBFBD><EFBFBD><EFBFBD>霂臭縑<EFBFBD>?
- [ ] 错误响应包含明确的错误码和错误信息
- [ ] 所有API都有文档说明
---
## 🔗 相关文档
**<EFBFBD><EFBFBD>嚗?*
- [API頝舐眏<EFBFBD><EFBFBD>](./04-API頝舐眏<EFBFBD><EFBFBD>.md) 潃?<3F><EFBFBD><E4BAA6><EFBFBD><EFBFBD>𡅅PI蝡舐<E89DA1>
**总览:**
- [API路由总览](./04-API路由总览.md) ⭐ 查看所有API端点
**璅⊥踎嚗?*
**模板:**
- [API设计模板](../_templates/API设计-模板.md)
**各模块设计:**
- [撟喳蝱<EFBFBD><EFBFBD><EFBFBD>(../01-撟喳蝱<E596B3><EFBFBD>撅?README.md)
- [<EFBFBD>𡁶鍂<EFBFBD><EFBFBD><EFBFBD>(../02-<2D>𡁶鍂<F0A181B6><EFBFBD>撅?README.md)
- [平台基础层](../01-平台基础层/README.md)
- [通用能力层](../02-通用能力层/README.md)
- [业务模块层](../03-业务模块/README.md)
---
**最后更新:** 2025-11-06
**维护人:** 技术架构师
**<EFBFBD><EFBFBD>𧋦嚗?* v2.0
**版本:** v2.0

View File

@@ -1,7 +1,7 @@
# 数据库全局视图
> **<EFBFBD><EFBFBD>嚗?* <20>𣂷<EFBFBD><F0A382B7><EFBFBD><EFBFBD>农chema<6D>諹”<E8ABB9><E2809D><EFBFBD>毺揣撘𤏪<E69298>靘蹂<E99D98><E8B982>交𪄳<E4BAA4>𣬚<EFBFBD><EFBFBD><E996AB><EFBFBD><E69285>唳旿<E594B3><EFBFBD>
> **霂衣<EFBFBD>霈曇恣嚗?* 霂瑟䰻<E7919F><EFBFBD><E79285><E288AA>?`01-<2D>唳旿摨栞挽霈?md`
> **目的:** 提供所有Schema和表的快速索引便于查找和理解全局数据架构
> **详细设计:** 请查看各模块的 `01-数据库设计.md`
> **数据库:** PostgreSQL 15+
> **最后更新:** 2025-11-06
@@ -9,202 +9,202 @@
## 📊 Schema划分策略
### Schema<EFBFBD>𠉛氖<EFBFBD><EFBFBD> 潃?
### Schema隔离原则 ⭐
**銝箔<EFBFBD><EFBFBD><EFBFBD><EFBFBD>chema<EFBFBD>𠉛氖嚗?*
1. <EFBFBD>?**璅<E79285><E288AA><EFBFBD><E7A589>?*嚗𡁏<E59A97>銝芯<E98A9D><E88AAF>⊥芋<E28AA5><EFBFBD><E59F88><EFBFBD><E7A589><EFBFBD>chema
2. <EFBFBD>?**<2A><EFBFBD><E88880><EFBFBD><E7A589>函蔡**嚗𡁜虾隞亙<E99A9E><E4BA99>砍紡<E7A08D><EFBFBD>銝芣芋<E88AA3><EFBFBD><E39B96>唳旿
3. <EFBFBD>?**<2A><><EFBFBD><EFBFBD>𠉛氖**嚗𡁜虾隞乩蛹銝滚<E98A9D>Schema霈曄蔭銝滚<E98A9D><E6BB9A><EFBFBD><EFBFBD>
4. <EFBFBD>?**<2A><EFBFBD><E8B8B9><EFBFBD><E8B3A2><EFBFBD>**嚗帋<E59A97><E5B88B>峕芋<E5B395>堒虾隞交<E99A9E><E4BAA4><EFBFBD><E8A9A8><EFBFBD><EFBFBD>?
**为什么需要Schema隔离**
1. **模块独立性**每个业务模块有独立的Schema
2. **支持独立部署**:可以单独导出某个模块的数据
3. **权限隔离**可以为不同Schema设置不同权限
4. **避免命名冲突**:不同模块可以有相同的表名
**Schema<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?*
**Schema命名规范:**
```
platform_schema # 撟喳蝱<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>曹澈嚗?
platform_schema # 平台基础层(全局共享)
aia_schema # AI智能问答
asl_schema # AI智能文献
pkb_schema # 銝芯犖<EFBFBD><EFBFBD>摨?
pkb_schema # 个人知识库
dc_schema # 数据清洗整理
ssa_schema # 智能统计分析
st_schema # 统计分析工具
rvw_schema # 稿件审查系统
admin_schema # 餈鞱𨯫蝞∠<EFBFBD>蝡荔<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>撟嗅<EFBFBD>platform_schema嚗?
admin_schema # 运营管理端(可选,可合并到platform_schema
```
---
## 📋 Schema一览表
| Schema | 霂湔<EFBFBD> | 銵冽㺭<E586BD>?| <20><EFBFBD>?| 霂衣<E99C82>霈曇恣 |
| Schema | 说明 | 表数量 | 状态 | 详细设计 |
|--------|------|--------|------|---------|
| **platform_schema** | 撟喳蝱<EFBFBD><EFBFBD>撅?| ~15銝?| <20>?雿輻鍂銝?| [<EFBFBD><EFBFBD>](#platform_schema-撟喳蝱<EFBFBD><EFBFBD>撅? |
| **aia_schema** | AI<EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ~8銝?| <20>?雿輻鍂銝?| [<5B><EFBFBD>](#aia_schema-ai<EFBFBD><EFBFBD><EFBFBD><EFBFBD>) |
| **pkb_schema** | 銝芯犖<EFBFBD><EFBFBD>摨?| ~5銝?| <20>?雿輻鍂銝?| [<EFBFBD><EFBFBD>](#pkb_schema-銝芯犖<EFBFBD><EFBFBD>摨? |
| **rvw_schema** | 蝔蹂辣摰⊥䰻蝟餌<EFBFBD> | ~6銝?| <20>?雿輻鍂銝?| [<5B><EFBFBD>](#rvw_schema-蝔蹂辣摰⊥䰻蝟餌<EFBFBD>) |
| **asl_schema** | AI<EFBFBD><EFBFBD><EFBFBD><EFBFBD>讃 | ~10銝?| <20>?霈曇恣銝?| [ASL/01-<EFBFBD>唳旿摨栞挽霈(../03-銝𡁜𦛚璅<E79285>/ASL-AI<41><EFBFBD><E7AE84><EFBFBD>讃/01-<2D>唳旿摨栞挽霈?md) |
| **dc_schema** | <EFBFBD>唳旿皜<EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ~8銝?| <20>?閫<><E996AB>銝?| 敺<>挽霈?|
| **ssa_schema** | <EFBFBD><EFBFBD>蝏蠘恣<EFBFBD><EFBFBD><EFBFBD> | ~10銝?| <20>?閫<><E996AB>銝?| 敺<>挽霈?|
| **st_schema** | 蝏蠘恣<EFBFBD><EFBFBD><EFBFBD>撌亙<EFBFBD> | ~5銝?| <20>?閫<><E996AB>銝?| 敺<>挽霈?|
| **platform_schema** | 平台基础层 | ~15个 | ✅ 使用中 | [查看](#platform_schema-平台基础层) |
| **aia_schema** | AI智能问答 | ~8个 | ✅ 使用中 | [查看](#aia_schema-ai智能问答) |
| **pkb_schema** | 个人知识库 | ~5个 | ✅ 使用中 | [查看](#pkb_schema-个人知识库) |
| **rvw_schema** | 稿件审查系统 | ~6个 | ✅ 使用中 | [查看](#rvw_schema-稿件审查系统) |
| **asl_schema** | AI智能文献 | ~10个 | ⏳ 设计中 | [ASL/01-数据库设计](../03-业务模块/ASL-AI智能文献/01-数据库设计.md) |
| **dc_schema** | 数据清洗整理 | ~8个 | ⏳ 规划中 | 待设计 |
| **ssa_schema** | 智能统计分析 | ~10个 | ⏳ 规划中 | 待设计 |
| **st_schema** | 统计分析工具 | ~5个 | ⏳ 规划中 | 待设计 |
**<EFBFBD>餉”<EFBFBD><EFBFBD>** ~70銝迎<EFBFBD><EFBFBD>摯嚗?
**总表数:** ~70个(预估)
---
## 🔍 platform_schema平台基础层
**<EFBFBD>諹提嚗?* 摮睃<E691AE><E79D83><EFBFBD><E585B8>曹澈<E69BB9><E6BE88><EFBFBD>唳㺭<E594B3><EFBFBD><E6AEB7><EFBFBD><EFBFBD><EFBFBD><E58A90>⊥芋<E28AA5><EFBFBD>靘肽<E99D98>
**职责:** 存储全局共享的平台数据,所有业务模块都依赖
**霂衣<EFBFBD>霈曇恣嚗?* [UAM/01-<EFBFBD>唳旿摨栞挽霈(../01-撟喳蝱<E596B3><EFBFBD>撅?01-<2D><EFBFBD>銝擧<E98A9D><E693A7>𣂷葉敹?UAM)/01-<EFBFBD>唳旿摨栞挽霈?md)
**详细设计:** [UAM/01-数据库设计](../01-平台基础层/01-用户与权限中心(UAM)/01-数据库设计.md)
### 核心表(用户与权限)
| 銵典<EFBFBD> | 霂湔<E99C82> | 霈啣<E99C88><E595A3><EFBFBD>隡?| 霂衣<E99C82>霈曇恣 |
| 表名 | 说明 | 记录数预估 | 详细设计 |
|------|------|-----------|---------|
| **users** | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>靽⊥<EFBFBD> | 10銝?撟?| [UAM/01-<EFBFBD>唳旿摨栞挽霈(../01-撟喳蝱<E596B3><EFBFBD>撅?01-<2D><EFBFBD>銝擧<E98A9D><E693A7>𣂷葉敹?UAM)/01-<EFBFBD>唳旿摨栞挽霈?md) |
| **users** | 用户基础信息 | 10万/年 | [UAM/01-数据库设计](../01-平台基础层/01-用户与权限中心(UAM)/01-数据库设计.md) |
| **roles** | 角色定义 | <100 | 同上 |
| **permissions** | 权限定义 | <500 | 同上 |
| **user_roles** | <EFBFBD><EFBFBD>-閫坿𠧧<E59DBF><EFBFBD> | 10銝?撟?| <20><EFBFBD> |
| **feature_flags** | Feature Flag<EFBFBD>滨蔭 潃?| <100 | <EFBFBD><EFBFBD> |
| **user_feature_flags** | <EFBFBD><EFBFBD>-Feature Flag<EFBFBD><EFBFBD> 潃?| 10銝?撟?| <20><EFBFBD> |
| **user_roles** | 用户-角色关联 | 10万/年 | 同上 |
| **feature_flags** | Feature Flag配置 ⭐ | <100 | 同上 |
| **user_feature_flags** | 用户-Feature Flag关联 ⭐ | 10万/年 | 同上 |
### LLM<EFBFBD><EFBFBD>銵?
### LLM相关表
| 銵典<EFBFBD> | 霂湔<E99C82> | 霈啣<E99C88><E595A3><EFBFBD>隡?| 霂衣<E99C82>霈曇恣 |
| 表名 | 说明 | 记录数预估 | 详细设计 |
|------|------|-----------|---------|
| **llm_models** | LLM<EFBFBD><EFBFBD>滨蔭 | <20 | [LLM蝵穃<EFBFBD>/01-<EFBFBD>唳旿摨栞挽霈(../02-<2D>𡁶鍂<F0A181B6><EFBFBD>撅?01-LLM憭扳芋<E689B3><EFBFBD><E8AEA0>?01-<2D>唳旿摨栞挽霈?md) |
| **llm_usage** | LLM雿輻鍂霈啣<EFBFBD> 潃?| 1000銝?撟?| <20><EFBFBD> |
| **llm_quotas** | LLM<EFBFBD><EFBFBD>蝞∠<EFBFBD> | 10銝?撟?| <20><EFBFBD> |
| **llm_models** | LLM模型配置 | <20 | [LLM网关/01-数据库设计](../02-通用能力层/01-LLM大模型网关/01-数据库设计.md) |
| **llm_usage** | LLM使用记录 ⭐ | 1000万/年 | 同上 |
| **llm_quotas** | LLM配额管理 | 10万/年 | 同上 |
### <EFBFBD>烐綉銝擧𠯫敹?
### 监控与日志
| 銵典<EFBFBD> | 霂湔<E99C82> | 霈啣<E99C88><E595A3><EFBFBD>隡?| 霂衣<E99C82>霈曇恣 |
| 表名 | 说明 | 记录数预估 | 详细设计 |
|------|------|-----------|---------|
| **admin_logs** | 蝞∠<EFBFBD><EFBFBD><EFBFBD>雿𨀣𠯫敹?| 10銝?撟?| [<5B>烐綉銝擧𠯫敹?01-<2D>唳旿摨栞挽霈(../01-撟喳蝱<E596B3><EFBFBD>撅?04-<2D>烐綉銝擧𠯫敹?01-<2D>唳旿摨栞挽霈?md) |
| **error_logs** | <EFBFBD>躰秤<EFBFBD><EFBFBD> | 100銝?撟?| <20><EFBFBD> |
| **audit_logs** | 摰∟恣<EFBFBD><EFBFBD> | 100銝?撟?| <20><EFBFBD> |
| **admin_logs** | 管理员操作日志 | 10万/年 | [监控与日志/01-数据库设计](../01-平台基础层/04-监控与日志/01-数据库设计.md) |
| **error_logs** | 错误日志 | 100万/年 | 同上 |
| **audit_logs** | 审计日志 | 100万/年 | 同上 |
### 系统配置
| 銵典<EFBFBD> | 霂湔<E99C82> | 霈啣<E99C88><E595A3><EFBFBD>隡?| 霂衣<E99C82>霈曇恣 |
| 表名 | 说明 | 记录数预估 | 详细设计 |
|------|------|-----------|---------|
| **system_configs** | 蝟餌<EFBFBD><EFBFBD>滨蔭 | <100 | [蝟餌<EFBFBD><EFBFBD>滨蔭/01-<2D>唳旿摨栞挽霈(../01-撟喳蝱<E596B3><EFBFBD>撅?05-蝟餌<E89D9F><E9A48C>滨蔭/01-<2D>唳旿摨栞挽霈?md) |
| **system_configs** | 系统配置 | <100 | [系统配置/01-数据库设计](../01-平台基础层/05-系统配置/01-数据库设计.md) |
| **prompt_templates** | Prompt模板 | <500 | 同上 |
| **announcements** | 系统公告 | <1000 | 同上 |
---
## <EFBFBD><EFBFBD> aia_schema嚗㇁I<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?
## 🤖 aia_schemaAI智能问答
**<EFBFBD>諹提嚗?* 摮睃<E691AE>AI<41><EFBFBD><E7AE84><EFBFBD><E6A183><EFBFBD><E8A9A8>唳旿嚗?2銝芣惣<E88AA3><EFBFBD><E8B3AD><EFBFBD>笆霂嘥<E99C82><E598A5><EFBFBD>
**职责:** 存储AI智能问答相关数据12个智能体、对话历史
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?撌脣<E6928C><E884A3>?
**霂衣<EFBFBD>霈曇恣嚗?* [AIA/01-<EFBFBD>唳旿摨栞挽霈(../03-銝𡁜𦛚璅<E79285>/AIA-AI<41><EFBFBD><E7AE84><EFBFBD>/01-<2D>唳旿摨栞挽霈?md)嚗<><E59A97><EFBFBD>𥕦遣嚗?
**状态:** ✅ 已实现
**详细设计:** [AIA/01-数据库设计](../03-业务模块/AIA-AI智能问答/01-数据库设计.md)(待创建)
### <EFBFBD><EFBFBD>銵?
### 核心表
| 銵典<EFBFBD> | 霂湔<E99C82> | 霈啣<E99C88><E595A3><EFBFBD>隡?|
| 表名 | 说明 | 记录数预估 |
|------|------|-----------|
| **conversations** | 撖寡<EFBFBD>隡朞<EFBFBD> | 100銝?撟?|
| **messages** | 撖寡<EFBFBD><EFBFBD><EFBFBD> | 1000銝?撟?|
| **agents** | <EFBFBD><EFBFBD>雿㯄<EFBFBD>蝵?| <20 |
| **conversation_contexts** | 撖寡<EFBFBD>銝𠹺<EFBFBD><EFBFBD>?| 100銝?撟?|
| **conversations** | 对话会话 | 100万/年 |
| **messages** | 对话消息 | 1000万/年 |
| **agents** | 智能体配置 | <20 |
| **conversation_contexts** | 对话上下文 | 100万/年 |
---
## <EFBFBD><EFBFBD> pkb_schema<EFBFBD>葵鈭箇䰻霂<EFBFBD><EFBFBD>嚗?
## 📚 pkb_schema(个人知识库)
**<EFBFBD>諹提嚗?* 摮睃<E691AE>銝芯犖<E88AAF><EFBFBD>摨瓐<E691A8><E79390><EFBFBD><EFBFBD><E78DA2><EFBFBD>AG<41><EFBFBD><E6A183><EFBFBD><E8A9A8>唳旿
**职责:** 存储个人知识库、文档、RAG问答相关数据
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?撌脣<E6928C><E884A3>?
**霂衣<EFBFBD>霈曇恣嚗?* [PKB/01-<EFBFBD>唳旿摨栞挽霈(../03-銝𡁜𦛚璅<E79285>/PKB-銝芯犖<E88AAF><EFBFBD>摨?01-<2D>唳旿摨栞挽霈?md)嚗<><E59A97><EFBFBD>𥕦遣嚗?
**状态:** ✅ 已实现
**详细设计:** [PKB/01-数据库设计](../03-业务模块/PKB-个人知识库/01-数据库设计.md)(待创建)
### <EFBFBD><EFBFBD>銵?
### 核心表
| 銵典<EFBFBD> | 霂湔<E99C82> | 霈啣<E99C88><E595A3><EFBFBD>隡?|
| 表名 | 说明 | 记录数预估 |
|------|------|-----------|
| **knowledge_bases** | <EFBFBD><EFBFBD>摨?| 30銝?撟?|
| **documents** | <EFBFBD><EFBFBD> | 300銝?撟?|
| **document_chunks** | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?| 3000銝?撟?|
| **kb_conversations** | <EFBFBD><EFBFBD>摨枏笆霂?| 100銝?撟?|
| **kb_messages** | <EFBFBD><EFBFBD>摨枏笆霂脲<EFBFBD><EFBFBD>?| 1000銝?撟?|
| **knowledge_bases** | 知识库 | 30万/年 |
| **documents** | 文档 | 300万/年 |
| **document_chunks** | 文档分块(向量化) | 3000万/年 |
| **kb_conversations** | 知识库对话 | 100万/年 |
| **kb_messages** | 知识库对话消息 | 1000万/年 |
---
## 📄 rvw_schema稿件审查系统
**<EFBFBD>諹提嚗?* 摮睃<E691AE>蝔蹂辣摰⊥䰻<E28AA5><E4B0BB><EFBFBD>隡唳𥁒<E594B3>羓㮾<E7BE93>單㺭<E596AE>?
**职责:** 存储稿件审查、评估报告相关数据
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?撌脣<E6928C><E884A3><EFBFBD><E5A086><EFBFBD>蝟餌<E89D9F>嚗?
**霂衣<EFBFBD>霈曇恣嚗?* [RVW/01-<EFBFBD>唳旿摨栞挽霈(../03-銝𡁜𦛚璅<E79285>/RVW-蝔蹂辣摰⊥䰻蝟餌<E89D9F>/01-<2D>唳旿摨栞挽霈?md)嚗<><E59A97><EFBFBD>𥕦遣嚗?
**状态:** ✅ 已实现(独立系统)
**详细设计:** [RVW/01-数据库设计](../03-业务模块/RVW-稿件审查系统/01-数据库设计.md)(待创建)
### <EFBFBD><EFBFBD>銵?
### 核心表
| 銵典<EFBFBD> | 霂湔<E99C82> | 霈啣<E99C88><E595A3><EFBFBD>隡?|
| 表名 | 说明 | 记录数预估 |
|------|------|-----------|
| **review_tasks** | 摰⊥䰻隞餃𦛚 | 10銝?撟?|
| **manuscripts** | 蝔蹂辣靽⊥<EFBFBD> | 10銝?撟?|
| **review_results** | 摰⊥䰻蝏𤘪<EFBFBD> | 10銝?撟?|
| **methodology_assessments** | <EFBFBD><EFBFBD>摮西<EFBFBD>隡?| 10銝?撟?|
| **guideline_assessments** | 蝔輻漲閫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>隡?| 10銝?撟?|
| **review_tasks** | 审查任务 | 10万/年 |
| **manuscripts** | 稿件信息 | 10万/年 |
| **review_results** | 审查结果 | 10万/年 |
| **methodology_assessments** | 方法学评估 | 10万/年 |
| **guideline_assessments** | 稿约规范性评估 | 10万/年 |
---
## <EFBFBD><EFBFBD> asl_schema嚗㇁I<EFBFBD><EFBFBD><EFBFBD><EFBFBD>讃嚗?
## 📖 asl_schemaAI智能文献
**<EFBFBD>諹提嚗?* 摮睃<E691AE><E79D83><EFBFBD>讃蝑偦<E89D91><EFBFBD><E589B9><EFBFBD><EFBFBD><EFBFBD><E7A194><EFBFBD><EFBFBD>鞟㮾<E99E9F>單㺭<E596AE>?
**职责:** 存储文献筛选、提取、分析相关数据
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?霈曇恣銝哨<E98A9D>P0隡睃<E99AA1>蝥改<E89DA5>
**霂衣<EFBFBD>霈曇恣嚗?* [ASL/01-<EFBFBD>唳旿摨栞挽霈(../03-銝𡁜𦛚璅<E79285>/ASL-AI<41><EFBFBD><E7AE84><EFBFBD>讃/01-<2D>唳旿摨栞挽霈?md)
**状态:** ⏳ 设计中P0优先级
**详细设计:** [ASL/01-数据库设计](../03-业务模块/ASL-AI智能文献/01-数据库设计.md)
### <EFBFBD><EFBFBD>銵剁<EFBFBD><EFBFBD><EFBFBD>嚗?
### 核心表(预览)
| 銵典<EFBFBD> | 霂湔<E99C82> | 霈啣<E99C88><E595A3><EFBFBD>隡?|
| 表名 | 说明 | 记录数预估 |
|------|------|-----------|
| **literature_projects** | <EFBFBD><EFBFBD>讃憿寧𤌍 | 10銝?撟?|
| **literature_items** | <EFBFBD><EFBFBD><EFBFBD>∠𤌍 | 1000銝?撟?|
| **pico_configs** | PICO蝥喳<EFBFBD><EFBFBD>㘾膄<EFBFBD><EFBFBD><EFBFBD> | 10銝?撟?|
| **screening_results** | 蝑偦<EFBFBD><EFBFBD><EFBFBD>?| 1000銝?撟?|
| **screening_history** | 蝑偦<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>皞荔<EFBFBD> | 1000銝?撟?|
| **extraction_tasks** | <EFBFBD>𣂼<EFBFBD>隞餃𦛚 | 100銝?撟?|
| **extraction_results** | <EFBFBD>𣂼<EFBFBD>蝏𤘪<EFBFBD> | 100銝?撟?|
| **literature_projects** | 文献项目 | 10万/年 |
| **literature_items** | 文献条目 | 1000万/年 |
| **pico_configs** | PICO纳入排除标准 | 10万/年 |
| **screening_results** | 筛选结果 | 1000万/年 |
| **screening_history** | 筛选历史(可回溯) | 1000万/年 |
| **extraction_tasks** | 提取任务 | 100万/年 |
| **extraction_results** | 提取结果 | 100万/年 |
---
## 🧹 dc_schema数据清洗整理
**<EFBFBD>諹提嚗?* 摮睃<E691AE><E79D83>唳旿皜<E697BF><E79A9C>隞餃𦛚<E9A483><F0A69B9A>TL<54>滨蔭<E6BBA8><E894AD>ER蝏𤘪<E89D8F>
**职责:** 存储数据清洗任务、ETL配置、NER结果
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?閫<><E996AB>銝哨<E98A9D>P1隡睃<E99AA1>蝥改<E89DA5>
**霂衣<EFBFBD>霈曇恣嚗?* 敺<>挽霈?
**状态:** ⏳ 规划中P1优先级
**详细设计:** 待设计
### <EFBFBD><EFBFBD>銵剁<EFBFBD><EFBFBD><EFBFBD>嚗?
### 核心表(预览)
| 銵典<EFBFBD> | 霂湔<E99C82> | 霈啣<E99C88><E595A3><EFBFBD>隡?|
| 表名 | 说明 | 记录数预估 |
|------|------|-----------|
| **cleaning_projects** | <EFBFBD><EFBFBD>憿寧𤌍 | 10銝?撟?|
| **data_sources** | <EFBFBD>唳旿皞?| 100銝?撟?|
| **etl_configs** | ETL<EFBFBD>滨蔭 | 10銝?撟?|
| **ner_tasks** | NER隞餃𦛚 | 100銝?撟?|
| **ner_results** | NER蝏𤘪<EFBFBD> | 1000銝?撟?|
| **cleaning_projects** | 清洗项目 | 10万/年 |
| **data_sources** | 数据源 | 100万/年 |
| **etl_configs** | ETL配置 | 10万/年 |
| **ner_tasks** | NER任务 | 100万/年 |
| **ner_results** | NER结果 | 1000万/年 |
---
## 🔗 跨Schema依赖关系
### 靘肽<EFBFBD><EFBFBD><EFBFBD> 潃?<3F><EFBFBD>
### 依赖规则 ⭐ 重要
**允许的依赖:**
```
<EFBFBD>?銝𡁜𦛚璅<E79285> <20>?platform_schema<EFBFBD><EFBFBD>霈詨<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD>?<3F>𡁶鍂<F0A181B6><EFBFBD> <20>?platform_schema<EFBFBD><EFBFBD>霈詨<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD>?銝𡁜𦛚璅<E79285>銋钅𡢿嚗<F0A1A2BF><E59A97><EFBCB9><EFBFBD>韏吔<E99F8F>
<EFBFBD>?platform_schema <EFBFBD>?銝𡁜𦛚璅<E79285><EFBFBD><E59A97><EFBFBD><EFBFBD>韏吔<E99F8F>
✅ 业务模块 → platform_schema(允许外键)
✅ 通用能力 → platform_schema(允许外键)
❌ 业务模块之间(禁止直接依赖)
platform_schema → 业务模块(反向依赖)
```
### 靘肽<EFBFBD><EFBFBD>喟頂<EFBFBD>?
### 依赖关系图
```
platform_schema.users (1)
<EFBFBD>?(N) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⊥芋<EFBFBD><EFBFBD>靘肽<EFBFBD><EFBFBD><EFBFBD>銵?
(N) 所有业务模块都依赖用户表
├── aia_schema.conversations
├── asl_schema.literature_projects
├── pkb_schema.knowledge_bases
@@ -215,67 +215,67 @@ platform_schema.users (1)
platform_schema.llm_usage (独立)
- 记录所有模块的LLM调用
- <EFBFBD><EFBFBD>module摮埈挾<EFBFBD><EFBFBD>嚗?AIA', 'ASL', 'PKB'蝑?
- 通过module字段区分:'AIA', 'ASL', 'PKB'
```
### 外键示例
```sql
-- <EFBFBD>?<3F><>捂嚗帋<E59A97><E5B88B>⊥芋<E28AA5><EFBFBD><E5A092>latform_schema
-- ✅ 允许业务模块引用platform_schema
CREATE TABLE asl_schema.literature_projects (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES platform_schema.users(id) ON DELETE CASCADE
);
-- <EFBFBD>?蝳<>迫嚗帋<E59A97><E5B88B>⊥芋<E28AA5>𦯀<EFBFBD><F0A6AF80><EFBFBD><E6B8AF><EFBFBD><E8A9A8>?
-- ❌ 禁止:业务模块之间互相引用
CREATE TABLE ssa_schema.analysis_projects (
id SERIAL PRIMARY KEY,
-- <EFBFBD>躰秤嚗帋<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞碶<EFBFBD><EFBFBD>⊥芋<EFBFBD>?
-- 错误:不能引用其他业务模块
literature_project_id INTEGER REFERENCES asl_schema.literature_projects(id)
);
-- <EFBFBD>?甇<><EFBFBD>𡁏<EFBFBD>嚗𡁻<E59A97><EFBFBD>user_id<EFBFBD><EFBFBD>
-- ✅ 正确做法:通过user_id关联
-- 在应用层处理跨模块关联,不在数据库层
```
---
## <EFBFBD><EFBFBD> <20>唳旿<E594B3><EFBFBD>霈∴<E99C88><EFBFBD>摯嚗?
## 📊 数据量统计(预估)
### 按Schema统计
| Schema | 銵冽㺭<EFBFBD>?| 撟游<E6929F><E6B8B8>輯扇敶閙㺭 | 摮睃<E691AE><EFBFBD>摯嚗?撟湛<E6929F> |
| Schema | 表数量 | 年增长记录数 | 存储预估5年 |
|--------|--------|------------|---------------|
| platform_schema | 15 | 1000銝?| 50GB |
| aia_schema | 8 | 1100銝?| 30GB |
| pkb_schema | 5 | 3300銝?| 200GB<EFBFBD><EFBFBD><EFBFBD>𧶏<EFBFBD> |
| rvw_schema | 6 | 50銝?| 5GB |
| asl_schema | 10 | 2100銝?| 50GB |
| dc_schema | 8 | 1100銝?| 100GB |
| ssa_schema | 10 | 500銝?| 50GB |
| st_schema | 5 | 100銝?| 10GB |
| **<EFBFBD>餉恣** | **~70** | **~4000銝?撟?* | **~500GB嚗?撟湛<E6929F>** |
| platform_schema | 15 | 1000| 50GB |
| aia_schema | 8 | 1100| 30GB |
| pkb_schema | 5 | 3300| 200GB(向量) |
| rvw_schema | 6 | 50| 5GB |
| asl_schema | 10 | 2100| 50GB |
| dc_schema | 8 | 1100| 100GB |
| ssa_schema | 10 | 500| 50GB |
| st_schema | 5 | 100| 10GB |
| **总计** | **~70** | **~4000万/年** | **~500GB5年** |
### 大表监控(年增长>100万
| 銵典<EFBFBD> | Schema | 撟游<EFBFBD><EFBFBD>?| 蝝<E89D9D>蝑𣇉裦 |
| 表名 | Schema | 年增长 | 索引策略 |
|------|--------|--------|---------|
| llm_usage | platform | 1000銝?| <20><EFBFBD><E39787><EFBFBD> |
| messages | aia | 1000銝?| <20>reated_at<EFBFBD> |
| document_chunks | pkb | 3000銝?| <20><EFBFBD><E89D9D> |
| literature_items | asl | 1000銝?| <20>roject_id<EFBFBD> |
| screening_results | asl | 1000銝?| 憭滚<E686AD><E89D9D> |
| llm_usage | platform | 1000万 | 按月分区 |
| messages | aia | 1000万 | 按created_at索引 |
| document_chunks | pkb | 3000万 | 向量索引 |
| literature_items | asl | 1000万 | 按project_id索引 |
| screening_results | asl | 1000万 | 复合索引 |
---
## <EFBFBD><EFBFBD> 敹恍<E695B9><E6818D><EFBFBD><EFBFBD><E69AB9>?
## 🔍 快速查找指南
### <EFBFBD>箸艶1嚗𡁏<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>銝芣芋<EFBFBD>?
### 场景1我要开发某个模块
1. 在上面的表格中找到对应的Schema
2. 点击"详细设计"链接
3. <EFBFBD><EFBFBD>霂交芋<EFBFBD><EFBFBD>摰峕㟲銵函<EFBFBD><EFBFBD>?
3. 查看该模块的完整表结构
### <EFBFBD>箸艶2嚗𡁏<EFBFBD><EFBFBD><EFBFBD>𧢲<EFBFBD>銝芾”<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
### 场景2我要查看某个表的结构
1. 先确定表属于哪个Schema根据功能判断
2. 转到对应模块的数据库设计文档
3. 搜索表名
@@ -286,53 +286,53 @@ CREATE TABLE ssa_schema.analysis_projects (
3. 在应用层处理跨模块关联,不在数据库层
### 场景4我要查看全局数据架构
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>敹恍<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>chema嚗?
2. <EFBFBD><EFBFBD>[<5B><EFBFBD>霈曇恣<E69B87>冽艶<E586BD>霄(../00-蝟餌<E89D9F><E9A48C><EFBFBD>霈曇恣/08-<2D><EFBFBD>霈曇恣<E69B87>冽艶<E586BD>?md)
1. 阅读本文档快速了解所有Schema
2. 查看[架构设计全景图](../00-系统总体设计/08-架构设计全景图.md)
---
## ⚠️ 重要提醒
### Schema<EFBFBD>𠉛氖<EFBFBD><EFBFBD><EFBFBD><EFBFBD>憿?
### Schema隔离的注意事项
**<EFBFBD>?甇<><EFBFBD>𡁏<EFBFBD>嚗?*
- 銝𡁜𦛚璅<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?`platform_schema.users`
- 頝冽芋<EFBFBD>埈㺭<EFBFBD><EFBFBD><EFBFBD>𥪜銁摨𠉛鍂撅<EFBFBD><EFBFBD><EFBFBD>?
- 雿輻鍂 `user_id + 銝𡁜𦛚ID` <EFBFBD><EFBFBD>䲮撘?
**✅ 正确做法:**
- 业务模块只引用 `platform_schema.users`
- 跨模块数据关联在应用层处理
- 使用 `user_id + 业务ID` 的方式
**<EFBFBD>?<3F>躰秤<E8BAB0>𡁏<EFBFBD>嚗?*
**❌ 错误做法:**
- 业务模块之间直接外键关联
- <EFBFBD>?`platform_schema` 銝剖<EFBFBD><EFBFBD><EFBFBD><EFBFBD>⊥㺭<EFBFBD>?
- `platform_schema` 中存储业务数据
- 不同模块使用相同的表名虽然Schema隔离了但容易混淆
### 性能优化建议
1. **憭扯”敹<EFBFBD><EFBFBD><EFBFBD><EFBFBD>亥砭**嚗<><E59A97> `llm_usage`<EFBFBD><EFBFBD>messages`嚗?
2. **<EFBFBD><EFBFBD>摮埈挾敹<EFBFBD><EFBFBD>删揣撘?*嚗<><E59A97> `user_id`<EFBFBD><EFBFBD>created_at`嚗?
3. **<EFBFBD><EFBFBD><EFBFBD>銵典<EFBFBD><EFBFBD>?*嚗<><E59A97><EFBFBD>?<3F>匧僑嚗<E58391><E59A97> `llm_usage`嚗?
1. **大表必须分页查询**(如 `llm_usage``messages`
2. **热点字段必须加索引**(如 `user_id``created_at`
3. **考虑表分区**(按月/按年,如 `llm_usage`
4. **定期归档历史数据**如1年前的日志
---
## 🔗 相关文档
**<EFBFBD><EFBFBD>嚗?*
- [<EFBFBD>唳旿摨栞挽霈∟<EFBFBD><EFBFBD><EFBFBD>(./01-<2D>唳旿摨栞挽霈∟<E99C88><E2889F>?md) 潃?敹<>
- [<EFBFBD>唳旿摨𤘪沲<EFBFBD><EFBFBD><EFBFBD>筕(../00-蝟餌<E89D9F><E9A48C><EFBFBD>霈曇恣/03-<2D>唳旿摨𤘪沲<F0A498AA><E6B2B2><EFBFBD>?md)
**规范:**
- [数据库设计规范](./01-数据库设计规范.md) ⭐ 必读
- [数据库架构说明](../00-系统总体设计/03-数据库架构说明.md)
**<EFBFBD>霈曇恣嚗?*
- [撟喳蝱<EFBFBD><EFBFBD><EFBFBD>(../01-撟喳蝱<E596B3><EFBFBD>撅?README.md)
- [<EFBFBD>𡁶鍂<EFBFBD><EFBFBD><EFBFBD>(../02-<2D>𡁶鍂<F0A181B6><EFBFBD>撅?README.md)
**模块设计:**
- [平台基础层](../01-平台基础层/README.md)
- [通用能力层](../02-通用能力层/README.md)
- [业务模块层](../03-业务模块/README.md)
**璅⊥踎嚗?*
- [<EFBFBD>唳旿摨栞挽霈⊥芋<EFBFBD>瓢(../_templates/<EFBFBD>唳旿摨栞挽霈?璅⊥踎.md)
**模板:**
- [数据库设计模板](../_templates/数据库设计-模板.md)
---
**最后更新:** 2025-11-06
**维护人:** 技术架构师
**<EFBFBD><EFBFBD>𧋦嚗?* v1.0
**版本:** v1.0

View File

@@ -1,8 +1,8 @@
# API路由总览
> **<EFBFBD><EFBFBD>嚗?* <20>𣂷<EFBFBD><F0A382B7><EFBFBD><EFBFBD>𡅅PI蝡舐<E89DA1><E88890><EFBFBD><EFBFBD>毺揣撘𤏪<E69298>靘蹂<E99D98><E8B982>交𪄳<E4BAA4><EFBFBD><E5B1B8>滩楝<E6BBA9><EFBFBD>蝒?
> **霂衣<EFBFBD>霈曇恣嚗?* 霂瑟䰻<E7919F><EFBFBD><E79285><E288AA>?`02-API霈曇恣.md`
> **<EFBFBD><EFBFBD>URL嚗?* `http://localhost:3001/api/v1`
> **目的:** 提供所有API端点的快速索引便于查找和避免路由冲突
> **详细设计:** 请查看各模块的 `02-API设计.md`
> **基础URL** `http://localhost:3001/api/v1`
> **最后更新:** 2025-11-06
---
@@ -13,9 +13,9 @@
```
/api/v{version}/{module}/{resource}/{id?}/{action?}
蝷箔<EFBFBD>嚗?
示例:
/api/v1/literature/projects # 获取文献项目列表
/api/v1/literature/projects/123 # <EFBFBD><EFBFBD>ID=123<EFBFBD><EFBFBD><EFBFBD>?
/api/v1/literature/projects/123 # 获取ID=123的项目
/api/v1/literature/projects/123/export # 导出项目
```
@@ -23,350 +23,350 @@
| 模块代码 | 路由前缀 | 说明 |
|---------|---------|------|
| 撟喳蝱<EFBFBD><EFBFBD>撅?| `/auth`, `/users`, `/admin` | 霈方<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?|
| 平台基础层 | `/auth`, `/users`, `/admin` | 认证、用户、管理 |
| LLM网关 | `/llm` | LLM调用 |
| AIA | `/chat`, `/agents` | AI智能问答 |
| ASL | `/literature` | AI智能文献 |
| PKB | `/knowledge-bases`, `/kb` | 銝芯犖<EFBFBD><EFBFBD>摨?|
| PKB | `/knowledge-bases`, `/kb` | 个人知识库 |
| DC | `/data-cleaning` | 数据清洗 |
| SSA | `/analysis` | 智能统计分析 |
| ST | `/tools` | 统计工具 |
| RVW | `/review` | 稿件审查 |
| ADMIN | `/admin` | 餈鞱𨯫蝞∠<EFBFBD>蝡?|
| ADMIN | `/admin` | 运营管理端 |
---
## <EFBFBD><EFBFBD> 霈方<E99C88>銝𡒊鍂<F0A1928A>瑞恣<E7919E><E681A3><EFBFBD>/api/v1/auth, /api/v1/users嚗?
## 🔐 认证与用户管理(/api/v1/auth, /api/v1/users
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?撌脣<E6928C><E884A3>?
**霂衣<EFBFBD>霈曇恣嚗?* [UAM/02-API霈曇恣](../01-撟喳蝱<EFBFBD><EFBFBD>撅?01-<2D><EFBFBD>銝擧<E98A9D><E693A7>𣂷葉敹?UAM)/02-API霈曇恣.md)<EFBFBD><EFBFBD><EFBFBD>𥕦遣嚗?
**状态:** ✅ 已实现
**详细设计:** [UAM/02-API设计](../01-平台基础层/01-用户与权限中心(UAM)/02-API设计.md)(待创建)
### 认证相关
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/auth/register` | POST | <EFBFBD><EFBFBD>瘜典<EFBFBD> | <EFBFBD>?|
| `/api/v1/auth/login` | POST | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>?|
| `/api/v1/auth/logout` | POST | <EFBFBD><EFBFBD><EFBFBD>餃枂 | <EFBFBD>?|
| `/api/v1/auth/refresh` | POST | <EFBFBD>瑟鰵Token | <EFBFBD>?|
| `/api/v1/auth/profile` | GET | <EFBFBD><EFBFBD>敶枏<EFBFBD><EFBFBD><EFBFBD>靽⊥<EFBFBD> | <EFBFBD>?|
| `/api/v1/auth/profile` | PUT | <EFBFBD>湔鰵敶枏<EFBFBD><EFBFBD><EFBFBD>靽⊥<EFBFBD> | <EFBFBD>?|
| `/api/v1/auth/register` | POST | 用户注册 | |
| `/api/v1/auth/login` | POST | 用户登录 | |
| `/api/v1/auth/logout` | POST | 用户登出 | |
| `/api/v1/auth/refresh` | POST | 刷新Token | |
| `/api/v1/auth/profile` | GET | 获取当前用户信息 | |
| `/api/v1/auth/profile` | PUT | 更新当前用户信息 | |
### 用户管理
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/users` | GET | <EFBFBD><EFBFBD><EFBFBD>𡑒”嚗<EFBFBD><EFBFBD>憿蛛<EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/users/:id` | GET | <EFBFBD><EFBFBD>霂行<EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/users/:id` | PUT | <EFBFBD>湔鰵<EFBFBD><EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/users/:id` | DELETE | <EFBFBD>𣳇膄<EFBFBD><EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/users` | GET | 用户列表(分页) | ADMIN |
| `/api/v1/users/:id` | GET | 用户详情 | ADMIN |
| `/api/v1/users/:id` | PUT | 更新用户 | ADMIN |
| `/api/v1/users/:id` | DELETE | 删除用户 | ADMIN |
---
## <EFBFBD><EFBFBD> LLM憭扳芋<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/api/v1/llm嚗?
## 🤖 LLM大模型网关(/api/v1/llm
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?敺<><E695BA><EFBFBD><EFBFBD>P0隡睃<E99AA1>蝥改<E89DA5>
**霂衣<EFBFBD>霈曇恣嚗?* [LLM蝵穃<EFBFBD>/02-API霈曇恣](../02-<EFBFBD>𡁶鍂<EFBFBD><EFBFBD>撅?01-LLM憭扳芋<E689B3><EFBFBD><E8AEA0>?02-API霈曇恣.md)
**状态:** ❌ 待实现P0优先级
**详细设计:** [LLM网关/02-API设计](../02-通用能力层/01-LLM大模型网关/02-API设计.md)
### LLM调用
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/llm/chat` | POST | LLM撖寡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?| <20>?|
| `/api/v1/llm/chat/stream` | POST | LLM撖寡<EFBFBD><EFBFBD><EFBFBD>撘莅SE嚗?| <20>?|
| `/api/v1/llm/quota` | GET | <EFBFBD>亥砭敶枏<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>?|
| `/api/v1/llm/usage` | GET | <EFBFBD>亥砭雿輻鍂蝏蠘恣 | <EFBFBD>?|
| `/api/v1/llm/models` | GET | <EFBFBD><EFBFBD><EFBFBD>舐鍂璅<EFBFBD><EFBFBD>𡑒” | <EFBFBD>?|
| `/api/v1/llm/chat` | POST | LLM对话(非流式) | ✅ |
| `/api/v1/llm/chat/stream` | POST | LLM对话流式SSE | ✅ |
| `/api/v1/llm/quota` | GET | 查询当前用户配额 | |
| `/api/v1/llm/usage` | GET | 查询使用统计 | |
| `/api/v1/llm/models` | GET | 获取可用模型列表 | |
---
## <EFBFBD> AI<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?api/v1/chat, /api/v1/agents嚗?
## 💬 AI智能问答(/api/v1/chat, /api/v1/agents
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?撌脣<E6928C><E884A3>?
**霂衣<EFBFBD>霈曇恣嚗?* [AIA/02-API霈曇恣](../03-銝𡁜𦛚璅<EFBFBD>/AIA-AI<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/02-API霈曇恣.md)<EFBFBD><EFBFBD><EFBFBD>𥕦遣嚗?
**状态:** ✅ 已实现
**详细设计:** [AIA/02-API设计](../03-业务模块/AIA-AI智能问答/02-API设计.md)(待创建)
### 对话管理
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/chat/conversations` | GET | 撖寡<EFBFBD><EFBFBD>𡑒” | <EFBFBD>?|
| `/api/v1/chat/conversations` | POST | <EFBFBD>𥕦遣撖寡<EFBFBD> | <EFBFBD>?|
| `/api/v1/chat/conversations/:id` | GET | 撖寡<EFBFBD>霂行<EFBFBD> | <EFBFBD>?|
| `/api/v1/chat/conversations/:id` | DELETE | <EFBFBD>𣳇膄撖寡<EFBFBD> | <EFBFBD>?|
| `/api/v1/chat/conversations/:id/messages` | GET | 撖寡<EFBFBD><EFBFBD><EFBFBD><EFBFBD>𡑒” | <EFBFBD>?|
| `/api/v1/chat/conversations/:id/messages` | POST | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?| <20>?|
| `/api/v1/chat/conversations` | GET | 对话列表 | |
| `/api/v1/chat/conversations` | POST | 创建对话 | |
| `/api/v1/chat/conversations/:id` | GET | 对话详情 | |
| `/api/v1/chat/conversations/:id` | DELETE | 删除对话 | |
| `/api/v1/chat/conversations/:id/messages` | GET | 对话消息列表 | |
| `/api/v1/chat/conversations/:id/messages` | POST | 发送消息 | ✅ |
### <EFBFBD><EFBFBD>雿梶恣<EFBFBD>?
### 智能体管理
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/agents` | GET | <EFBFBD><EFBFBD>雿枏<EFBFBD>銵剁<EFBFBD>12銝迎<EFBFBD> | <EFBFBD>?|
| `/api/v1/agents/:id` | GET | <EFBFBD><EFBFBD>雿栞祕<EFBFBD>?| <20>?|
| `/api/v1/agents` | GET | 智能体列表12个 | |
| `/api/v1/agents/:id` | GET | 智能体详情 | ✅ |
---
## <EFBFBD><EFBFBD> AI<EFBFBD><EFBFBD><EFBFBD><EFBFBD>讃嚗?api/v1/literature嚗?
## 📖 AI智能文献(/api/v1/literature
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?霈曇恣銝哨<E98A9D>P0隡睃<E99AA1>蝥改<E89DA5>
**霂衣<EFBFBD>霈曇恣嚗?* [ASL/02-API霈曇恣](../03-銝𡁜𦛚璅<EFBFBD>/ASL-AI<EFBFBD><EFBFBD><EFBFBD><EFBFBD>/02-API霈曇恣.md)
**状态:** ⏳ 设计中P0优先级
**详细设计:** [ASL/02-API设计](../03-业务模块/ASL-AI智能文献/02-API设计.md)
### 项目管理
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/literature/projects` | GET | <EFBFBD><EFBFBD>讃憿寧𤌍<EFBFBD>𡑒” | <EFBFBD>?|
| `/api/v1/literature/projects` | POST | <EFBFBD>𥕦遣<EFBFBD><EFBFBD>讃憿寧𤌍 | <EFBFBD>?|
| `/api/v1/literature/projects/:id` | GET | 憿寧𤌍霂行<EFBFBD> | <EFBFBD>?|
| `/api/v1/literature/projects/:id` | PUT | <EFBFBD>湔鰵憿寧𤌍 | <EFBFBD>?|
| `/api/v1/literature/projects/:id` | DELETE | <EFBFBD>𣳇膄憿寧𤌍 | <EFBFBD>?|
| `/api/v1/literature/projects` | GET | 文献项目列表 | |
| `/api/v1/literature/projects` | POST | 创建文献项目 | |
| `/api/v1/literature/projects/:id` | GET | 项目详情 | |
| `/api/v1/literature/projects/:id` | PUT | 更新项目 | |
| `/api/v1/literature/projects/:id` | DELETE | 删除项目 | |
### 文献筛选(标题摘要初筛)⭐
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/literature/projects/:id/items/import` | POST | 撖澆<EFBFBD>CSV<EFBFBD><EFBFBD> | <EFBFBD>?|
| `/api/v1/literature/projects/:id/pico` | POST | <EFBFBD>滨蔭PICO<EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>?|
| `/api/v1/literature/projects/:id/pico` | GET | <EFBFBD><EFBFBD>PICO<EFBFBD>滨蔭 | <EFBFBD>?|
| `/api/v1/literature/projects/:id/screening/title` | POST | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>?|
| `/api/v1/literature/projects/:id/screening/status` | GET | <EFBFBD>亥砭蝑偦<EFBFBD><EFBFBD>摨?| <20>?|
| `/api/v1/literature/projects/:id/screening/results` | GET | <EFBFBD><EFBFBD>蝑偦<EFBFBD><EFBFBD><EFBFBD>?| <20>?|
| `/api/v1/literature/projects/:id/screening/export` | POST | 撖澆枂Excel | <EFBFBD>?|
| `/api/v1/literature/projects/:id/items/import` | POST | 导入CSV文件 | |
| `/api/v1/literature/projects/:id/pico` | POST | 配置PICO标准 | |
| `/api/v1/literature/projects/:id/pico` | GET | 获取PICO配置 | |
| `/api/v1/literature/projects/:id/screening/title` | POST | 执行标题摘要初筛 | |
| `/api/v1/literature/projects/:id/screening/status` | GET | 查询筛选进度 | ✅ |
| `/api/v1/literature/projects/:id/screening/results` | GET | 获取筛选结果 | ✅ |
| `/api/v1/literature/projects/:id/screening/export` | POST | 导出Excel | |
### <EFBFBD><EFBFBD>讃蝑偦<EFBFBD><EFBFBD><EFBFBD><EFBFBD>憭滨<EFBFBD>嚗?
### 文献筛选(全文复筛)
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/literature/projects/:id/screening/fulltext` | POST | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝑偦<EFBFBD>?| <20>?|
| `/api/v1/literature/projects/:id/screening/fulltext/status` | GET | <EFBFBD>亥砭餈𥕦漲 | <EFBFBD>?|
| `/api/v1/literature/projects/:id/screening/fulltext` | POST | 执行全文筛选 | ✅ |
| `/api/v1/literature/projects/:id/screening/fulltext/status` | GET | 查询进度 | |
---
## <EFBFBD><EFBFBD> 銝芯犖<E88AAF><EFBFBD>摨橒<E691A8>/api/v1/knowledge-bases嚗?
## 📚 个人知识库(/api/v1/knowledge-bases
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?撌脣<E6928C><E884A3>?
**霂衣<EFBFBD>霈曇恣嚗?* [PKB/02-API霈曇恣](../03-銝𡁜𦛚璅<EFBFBD>/PKB-銝芯犖<E88AAF><EFBFBD>摨?02-API霈曇恣.md)<EFBFBD><EFBFBD><EFBFBD>𥕦遣嚗?
**状态:** ✅ 已实现
**详细设计:** [PKB/02-API设计](../03-业务模块/PKB-个人知识库/02-API设计.md)(待创建)
### <EFBFBD><EFBFBD>摨梶恣<EFBFBD>?
### 知识库管理
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/knowledge-bases` | GET | <EFBFBD><EFBFBD>摨枏<EFBFBD>銵?| <20>?|
| `/api/v1/knowledge-bases` | POST | <EFBFBD>𥕦遣<EFBFBD><EFBFBD>摨?| <20>?|
| `/api/v1/knowledge-bases/:id` | GET | <EFBFBD><EFBFBD>摨栞祕<EFBFBD>?| <20>?|
| `/api/v1/knowledge-bases/:id` | PUT | <EFBFBD>湔鰵<EFBFBD><EFBFBD>摨?| <20>?|
| `/api/v1/knowledge-bases/:id` | DELETE | <EFBFBD>𣳇膄<EFBFBD><EFBFBD>摨?| <20>?|
| `/api/v1/knowledge-bases` | GET | 知识库列表 | ✅ |
| `/api/v1/knowledge-bases` | POST | 创建知识库 | ✅ |
| `/api/v1/knowledge-bases/:id` | GET | 知识库详情 | ✅ |
| `/api/v1/knowledge-bases/:id` | PUT | 更新知识库 | ✅ |
| `/api/v1/knowledge-bases/:id` | DELETE | 删除知识库 | ✅ |
### 文档管理
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/knowledge-bases/:id/documents` | GET | <EFBFBD><EFBFBD><EFBFBD>𡑒” | <EFBFBD>?|
| `/api/v1/knowledge-bases/:id/documents` | POST | 銝𠹺<EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>?|
| `/api/v1/knowledge-bases/:id/documents/:docId` | GET | <EFBFBD><EFBFBD>﹝霂行<EFBFBD> | <EFBFBD>?|
| `/api/v1/knowledge-bases/:id/documents/:docId` | DELETE | <EFBFBD>𣳇膄<EFBFBD><EFBFBD> | <EFBFBD>?|
| `/api/v1/knowledge-bases/:id/documents` | GET | 文档列表 | |
| `/api/v1/knowledge-bases/:id/documents` | POST | 上传文档 | |
| `/api/v1/knowledge-bases/:id/documents/:docId` | GET | 文档详情 | |
| `/api/v1/knowledge-bases/:id/documents/:docId` | DELETE | 删除文档 | |
### RAG问答
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/knowledge-bases/:id/chat` | POST | <EFBFBD><EFBFBD>摨㯄䔮蝑?| <20>?|
| `/api/v1/knowledge-bases/:id/search` | GET | 霂凋<EFBFBD><EFBFBD>蝝?| <20>?|
| `/api/v1/knowledge-bases/:id/chat` | POST | 知识库问答 | ✅ |
| `/api/v1/knowledge-bases/:id/search` | GET | 语义检索 | ✅ |
---
## <EFBFBD><20>唳旿皜<E697BF><E79A9C><EFBFBD><EFBFBD>嚗?api/v1/data-cleaning嚗?
## 🧹 数据清洗整理(/api/v1/data-cleaning
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?閫<><E996AB>銝哨<E98A9D>P1隡睃<E99AA1>蝥改<E89DA5>
**霂衣<EFBFBD>霈曇恣嚗?* 敺<>挽霈?
**状态:** ⏳ 规划中P1优先级
**详细设计:** 待设计
### 清洗项目
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/data-cleaning/projects` | GET | <EFBFBD><EFBFBD>憿寧𤌍<EFBFBD>𡑒” | <EFBFBD>?|
| `/api/v1/data-cleaning/projects` | POST | <EFBFBD>𥕦遣皜<EFBFBD><EFBFBD>憿寧𤌍 | <EFBFBD>?|
| `/api/v1/data-cleaning/projects/:id` | GET | 憿寧𤌍霂行<EFBFBD> | <EFBFBD>?|
| `/api/v1/data-cleaning/projects` | GET | 清洗项目列表 | |
| `/api/v1/data-cleaning/projects` | POST | 创建清洗项目 | |
| `/api/v1/data-cleaning/projects/:id` | GET | 项目详情 | |
### ETL配置
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/data-cleaning/projects/:id/etl` | POST | <EFBFBD>滨蔭ETL閫<EFBFBD><EFBFBD> | <EFBFBD>?|
| `/api/v1/data-cleaning/projects/:id/execute` | POST | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞餃𦛚 | <EFBFBD>?|
| `/api/v1/data-cleaning/projects/:id/etl` | POST | 配置ETL规则 | |
| `/api/v1/data-cleaning/projects/:id/execute` | POST | 执行清洗任务 | |
---
## <EFBFBD><EFBFBD> <20><EFBFBD>蝏蠘恣<E8A098><E681A3><EFBFBD>嚗?api/v1/analysis嚗?
## 📊 智能统计分析(/api/v1/analysis
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?閫<><E996AB>銝哨<E98A9D>P2隡睃<E99AA1>蝥改<E89DA5>
**霂衣<EFBFBD>霈曇恣嚗?* 敺<>挽霈?
**状态:** ⏳ 规划中P2优先级
**详细设计:** 待设计
### 分析项目
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/analysis/projects` | GET | <EFBFBD><EFBFBD><EFBFBD>憿寧𤌍<EFBFBD>𡑒” | <EFBFBD>?|
| `/api/v1/analysis/projects` | POST | <EFBFBD>𥕦遣<EFBFBD><EFBFBD><EFBFBD>憿寧𤌍 | <EFBFBD>?|
| `/api/v1/analysis/projects/:id/execute` | POST | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>?|
| `/api/v1/analysis/projects` | GET | 分析项目列表 | |
| `/api/v1/analysis/projects` | POST | 创建分析项目 | |
| `/api/v1/analysis/projects/:id/execute` | POST | 执行分析 | |
---
## <EFBFBD>圲 蝏蠘恣<E8A098><E681A3><EFBFBD>撌亙<E6928C>嚗?api/v1/tools嚗?
## 🔧 统计分析工具(/api/v1/tools
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?閫<><E996AB>銝哨<E98A9D>P2隡睃<E99AA1>蝥改<E89DA5>
**霂衣<EFBFBD>霈曇恣嚗?* 敺<>挽霈?
**状态:** ⏳ 规划中P2优先级
**详细设计:** 待设计
### 工具调用
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/tools` | GET | 撌亙<EFBFBD><EFBFBD>𡑒”嚗?00+嚗?| <20>?|
| `/api/v1/tools/:id` | GET | 撌亙<EFBFBD>霂行<EFBFBD> | <EFBFBD>?|
| `/api/v1/tools/:id/execute` | POST | <EFBFBD><EFBFBD>撌亙<EFBFBD> | <EFBFBD>?|
| `/api/v1/tools` | GET | 工具列表100+ | ✅ |
| `/api/v1/tools/:id` | GET | 工具详情 | |
| `/api/v1/tools/:id/execute` | POST | 执行工具 | |
---
## <EFBFBD><EFBFBD> 蝔蹂辣摰⊥䰻蝟餌<E89D9F>嚗?api/v1/review嚗?
## 📄 稿件审查系统(/api/v1/review
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?撌脣<E6928C><E884A3><EFBFBD><E5A086><EFBFBD>蝟餌<E89D9F>嚗?
**霂衣<EFBFBD>霈曇恣嚗?* [RVW/02-API霈曇恣](../03-銝𡁜𦛚璅<EFBFBD>/RVW-蝔蹂辣摰⊥䰻蝟餌<E89D9F>/02-API霈曇恣.md)<EFBFBD><EFBFBD><EFBFBD>𥕦遣嚗?
**状态:** ✅ 已实现(独立系统)
**详细设计:** [RVW/02-API设计](../03-业务模块/RVW-稿件审查系统/02-API设计.md)(待创建)
### 审查任务
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/review/tasks` | GET | 摰⊥䰻隞餃𦛚<EFBFBD>𡑒” | <EFBFBD>?|
| `/api/v1/review/tasks` | POST | <EFBFBD>𥕦遣摰⊥䰻隞餃𦛚 | <EFBFBD>?|
| `/api/v1/review/tasks/:id` | GET | 隞餃𦛚霂行<EFBFBD> | <EFBFBD>?|
| `/api/v1/review/tasks/:id/execute` | POST | <EFBFBD><EFBFBD>摰⊥䰻 | <EFBFBD>?|
| `/api/v1/review/tasks/:id/report` | GET | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗㇊DF嚗?| <20>?|
| `/api/v1/review/tasks` | GET | 审查任务列表 | |
| `/api/v1/review/tasks` | POST | 创建审查任务 | |
| `/api/v1/review/tasks/:id` | GET | 任务详情 | |
| `/api/v1/review/tasks/:id/execute` | POST | 执行审查 | |
| `/api/v1/review/tasks/:id/report` | GET | 生成报告PDF | ✅ |
---
## <EFBFBD><EFBFBD>儭?餈鞱𨯫蝞∠<E89D9E>蝡荔<E89DA1>/api/v1/admin嚗?
## 🛠️ 运营管理端(/api/v1/admin
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?閫<><E996AB>銝哨<E98A9D>P1隡睃<E99AA1>蝥改<E89DA5>
**霂衣<EFBFBD>霈曇恣嚗?* [ADMIN/02-API霈曇恣](../03-銝𡁜𦛚璅<EFBFBD>/ADMIN-餈鞱𨯫蝞∠<EFBFBD>蝡?02-API霈曇恣.md)
**状态:** ⏳ 规划中P1优先级
**详细设计:** [ADMIN/02-API设计](../03-业务模块/ADMIN-运营管理端/02-API设计.md)
### <EFBFBD><EFBFBD>蝞∠<EFBFBD> 潃?
### 用户管理 ⭐
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/admin/users` | GET | <EFBFBD><EFBFBD><EFBFBD>𡑒” | <EFBFBD>?ADMIN |
| `/api/v1/admin/users/:id` | GET | <EFBFBD><EFBFBD>霂行<EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/admin/users/:id` | PUT | <EFBFBD>湔鰵<EFBFBD><EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/admin/users/:id/plan` | PUT | 靽格㺿憟烾<EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/admin/users/:id/disable` | POST | <EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/admin/users` | GET | 用户列表 | ADMIN |
| `/api/v1/admin/users/:id` | GET | 用户详情 | ADMIN |
| `/api/v1/admin/users/:id` | PUT | 更新用户 | ADMIN |
| `/api/v1/admin/users/:id/plan` | PUT | 修改套餐 | ADMIN |
| `/api/v1/admin/users/:id/disable` | POST | 禁用用户 | ADMIN |
### Feature Flag蝞∠<EFBFBD> 潃?
### Feature Flag管理 ⭐
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/admin/feature-flags` | GET | Flag<EFBFBD>𡑒” | <EFBFBD>?ADMIN |
| `/api/v1/admin/feature-flags` | POST | <EFBFBD>𥕦遣Flag | <EFBFBD>?ADMIN |
| `/api/v1/admin/feature-flags/:id` | PUT | <EFBFBD>湔鰵Flag | <EFBFBD>?ADMIN |
| `/api/v1/admin/users/:id/flags` | GET | <EFBFBD><EFBFBD>Flag | <EFBFBD>?ADMIN |
| `/api/v1/admin/users/:id/flags` | PUT | <EFBFBD>湔鰵<EFBFBD><EFBFBD>Flag | <EFBFBD>?ADMIN |
| `/api/v1/admin/feature-flags` | GET | Flag列表 | ADMIN |
| `/api/v1/admin/feature-flags` | POST | 创建Flag | ADMIN |
| `/api/v1/admin/feature-flags/:id` | PUT | 更新Flag | ADMIN |
| `/api/v1/admin/users/:id/flags` | GET | 用户Flag | ADMIN |
| `/api/v1/admin/users/:id/flags` | PUT | 更新用户Flag | ADMIN |
### LLM<EFBFBD>蝞∠<EFBFBD> 潃?
### LLM模型管理 ⭐
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/admin/llm/models` | GET | <EFBFBD><EFBFBD>𡑒” | <EFBFBD>?ADMIN |
| `/api/v1/admin/llm/models` | POST | 瘛餃<EFBFBD><EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/admin/llm/models/:id` | PUT | <EFBFBD>湔鰵璅<EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/admin/llm/usage` | GET | LLM雿輻鍂蝏蠘恣 | <EFBFBD>?ADMIN |
| `/api/v1/admin/llm/cost-analysis` | GET | <EFBFBD>鞉𧋦<EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/admin/llm/models` | GET | 模型列表 | ADMIN |
| `/api/v1/admin/llm/models` | POST | 添加模型 | ADMIN |
| `/api/v1/admin/llm/models/:id` | PUT | 更新模型 | ADMIN |
| `/api/v1/admin/llm/usage` | GET | LLM使用统计 | ADMIN |
| `/api/v1/admin/llm/cost-analysis` | GET | 成本分析 | ADMIN |
### Prompt管理
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/admin/prompts` | GET | Prompt<EFBFBD>𡑒” | <EFBFBD>?ADMIN |
| `/api/v1/admin/prompts` | POST | <EFBFBD>𥕦遣Prompt | <EFBFBD>?ADMIN |
| `/api/v1/admin/prompts/:id` | PUT | <EFBFBD>湔鰵Prompt | <EFBFBD>?ADMIN |
| `/api/v1/admin/prompts` | GET | Prompt列表 | ADMIN |
| `/api/v1/admin/prompts` | POST | 创建Prompt | ADMIN |
| `/api/v1/admin/prompts/:id` | PUT | 更新Prompt | ADMIN |
### 日志查询
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/admin/logs` | GET | <EFBFBD><EFBFBD><EFBFBD>𡑒” | <EFBFBD>?ADMIN |
| `/api/v1/admin/logs/errors` | GET | <EFBFBD>躰秤<EFBFBD><EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/admin/logs/operations` | GET | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>?ADMIN |
| `/api/v1/admin/logs` | GET | 日志列表 | ADMIN |
| `/api/v1/admin/logs/errors` | GET | 错误日志 | ADMIN |
| `/api/v1/admin/logs/operations` | GET | 操作日志 | ADMIN |
### 数据报表
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| `/api/v1/admin/reports/overview` | GET | <EFBFBD><EFBFBD><EFBFBD>唳旿 | <EFBFBD>?ADMIN |
| `/api/v1/admin/reports/users` | GET | <EFBFBD><EFBFBD>瘣餉<EFBFBD>摨?| <20>?ADMIN |
| `/api/v1/admin/reports/features` | GET | <EFBFBD><EFBFBD>雿輻鍂<EFBFBD>?| <20>?ADMIN |
| `/api/v1/admin/reports/llm` | GET | LLM蝏蠘恣 | <EFBFBD>?ADMIN |
| `/api/v1/admin/reports/overview` | GET | 总览数据 | ADMIN |
| `/api/v1/admin/reports/users` | GET | 用户活跃度 | ✅ ADMIN |
| `/api/v1/admin/reports/features` | GET | 功能使用率 | ✅ ADMIN |
| `/api/v1/admin/reports/llm` | GET | LLM统计 | ADMIN |
---
## 📊 路由统计
### <EFBFBD>㗇芋<EFBFBD><EFBFBD>霈?
### 按模块统计
| <EFBFBD> | 蝡舐<E89DA1><E88890><EFBFBD> | <20><EFBFBD>?|
| 模块 | 端点数量 | 状态 |
|------|---------|------|
| 霈方<EFBFBD>銝𡒊鍂<EFBFBD>?| 10 | <20>?撌脣<E6928C><E884A3>?|
| LLM蝵穃<EFBFBD> | 5 | <EFBFBD>?敺<><E695BA><EFBFBD>?|
| AI<EFBFBD><EFBFBD><EFBFBD><EFBFBD> | 8 | <EFBFBD>?撌脣<E6928C><E884A3>?|
| AI<EFBFBD><EFBFBD><EFBFBD><EFBFBD> | 15 | <EFBFBD>?霈曇恣銝?|
| 銝芯犖<EFBFBD><EFBFBD>摨?| 10 | <20>?撌脣<E6928C><E884A3>?|
| <EFBFBD>唳旿皜<EFBFBD><EFBFBD> | 5 | <EFBFBD>?閫<><E996AB>銝?|
| <EFBFBD><EFBFBD>蝏蠘恣<EFBFBD><EFBFBD><EFBFBD> | 3 | <20>?閫<><E996AB>銝?|
| 蝏蠘恣撌亙<EFBFBD> | 3 | <EFBFBD>?閫<><E996AB>銝?|
| 蝔蹂辣摰⊥䰻 | 5 | <EFBFBD>?撌脣<E6928C><E884A3>?|
| 餈鞱𨯫蝞∠<EFBFBD>蝡?| 20 | <20>?閫<><E996AB>銝?|
| 认证与用户 | 10 | ✅ 已实现 |
| LLM网关 | 5 | ❌ 待实现 |
| AI智能问答 | 8 | ✅ 已实现 |
| AI智能文献 | 15 | ⏳ 设计中 |
| 个人知识库 | 10 | ✅ 已实现 |
| 数据清洗 | 5 | ⏳ 规划中 |
| 智能统计分析 | 3 | ⏳ 规划中 |
| 统计工具 | 3 | ⏳ 规划中 |
| 稿件审查 | 5 | ✅ 已实现 |
| 运营管理端 | 20 | ⏳ 规划中 |
| **总计** | **~85** | - |
---
## <EFBFBD>𩤃<EFBFBD> 頝舐眏<E88890><EFBFBD><EFBFBD><E79289>?
## ⚠️ 路由冲突检查
### 潜在冲突
**<EFBFBD>?<3F><EFBFBD><E8B8B9><EFBFBD>嚗?*
**❌ 避免冲突:**
```
# <EFBFBD>躰秤嚗𡁏芋<EFBFBD><EFBFBD>蝘啣<EFBFBD>蝒?
# 错误:模块名称冲突
/api/v1/admin/users # 管理端的用户管理
/api/v1/users # 平台层的用户管理
# <EFBFBD>嚗𡁏<EFBFBD>蝖桀躹<EFBFBD>?
# 正确:明确区分
/api/v1/auth/profile # 当前用户信息
/api/v1/admin/users # 管理端用户CRUD
```
---
## <EFBFBD><EFBFBD> 敹恍<E695B9><E6818D><EFBFBD><EFBFBD><E69AB9>?
## 🔍 快速查找指南
### 场景1查找某个模块的所有API
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>銵冽聢銝剜𪄳<EFBFBD>啣笆摨娍芋<EFBFBD>?
1. 在上面的表格中找到对应模块
2. 点击"详细设计"链接
3. 查看该模块的完整API文档
### 场景2设计新API端点
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝖桐<EFBFBD>頝舐眏銝滚<EFBFBD>蝒?
1. 查看本文档,确保路由不冲突
2. 参考[API设计规范](./02-API设计规范.md)
3. 使用[API设计模板](../_templates/API设计-模板.md)
### 场景3查看全局API架构
1. 阅读本文档(快速了解所有端点)
2. <EFBFBD><EFBFBD>[<5B><EFBFBD>霈曇恣<E69B87>冽艶<E586BD>霄(../00-蝟餌<E89D9F><E9A48C><EFBFBD>霈曇恣/08-<2D><EFBFBD>霈曇恣<E69B87>冽艶<E586BD>?md)
2. 查看[架构设计全景图](../00-系统总体设计/08-架构设计全景图.md)
---
## 🔗 相关文档
**<EFBFBD><EFBFBD>嚗?*
- [API霈曇恣閫<EFBFBD><EFBFBD>](./02-API霈曇恣閫<EFBFBD><EFBFBD>.md) 潃?敹<>
- [霈方<EFBFBD>銝擧<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(./02-API霈曇恣閫<E681A3><E996AB>.md#霈方<EFBFBD>銝擧<EFBFBD><EFBFBD>?
**规范:**
- [API设计规范](./02-API设计规范.md) ⭐ 必读
- [认证与授权规范](./02-API设计规范.md#认证与授权)
**璅⊥踎嚗?*
**模板:**
- [API设计模板](../_templates/API设计-模板.md)
**数据库:**
@@ -376,7 +376,7 @@
**最后更新:** 2025-11-06
**维护人:** 技术架构师
**<EFBFBD><EFBFBD>𧋦嚗?* v1.0
**版本:** v1.0

View File

@@ -1,8 +1,9 @@
# 代码规范
> **鐗堟湰锛?* v1.0
> **鍒涘缓鏃ユ湡锛?* 2025-10-10
> **閫傜敤鑼冨洿锛?* 鍓嶇<E98D93>锛圧eact/TypeScript锛? 鍚庣<E98D9A>锛圢ode.js/TypeScript锛?
> **版本:** v1.0
> **创建日期:** 2025-10-10
> **适用范围:** 前端React/TypeScript+ 后端Node.js/TypeScript
---
## 📋 目录
@@ -17,26 +18,29 @@
---
## 馃専 骞冲彴鑳藉姏浣跨敤瑙勮寖锛?025-11-16 鏂板<EFBFBD>锛?
> **猸?閲嶈<E996B2>鎻愮ず**锛氬钩鍙板凡鎻愪緵瀹屾暣鐨勫熀纭€璁炬柦鏈嶅姟
> **璇︾粏瑙勮寖**锛歔浜戝師鐢熷紑鍙戣<E98D99>鑼僝(./08-浜戝師鐢熷紑鍙戣<E98D99>鑼?md)
## 🌟 平台能力使用规范2025-11-16 新增)
> **⭐ 重要提示**:平台已提供完整的基础设施服务
> **详细规范**[云原生开发规范](./08-云原生开发规范.md)
> **详细文档**[平台基础设施规划](../09-架构实施/04-平台基础设施规划.md)
### 蹇呴』澶嶇敤鐨勫钩鍙版湇鍔?
**涓氬姟妯″潡锛圓SL/AIA/PKB/DC绛夛級绂佹<E7BB82>閲嶅<E996B2>瀹炵幇浠ヤ笅鍔熻兘锛?*
### 必须复用的平台服务
| 鏈嶅姟 | 瀵煎叆鏂瑰紡 | 鐢ㄩ€?|
**业务模块ASL/AIA/PKB/DC等禁止重复实现以下功能**
| 服务 | 导入方式 | 用途 |
|------|---------|------|
| **存储服务** | `import { storage } from '@/common/storage'` | 文件上传下载 |
| **鏃ュ織绯荤粺** | `import { logger } from '@/common/logging'` | 鏍囧噯鍖栨棩蹇?|
| **寮傛<EFBFBD>浠诲姟** | `import { jobQueue } from '@/common/jobs'` | 闀挎椂闂翠换鍔?|
| **缂撳瓨鏈嶅姟** | `import { cache } from '@/common/cache'` | 鍒嗗竷寮忕紦瀛?|
| **鏁版嵁搴?* | `import { prisma } from '@/config/database'` | 鏁版嵁搴撴搷浣?|
| **日志系统** | `import { logger } from '@/common/logging'` | 标准化日志 |
| **异步任务** | `import { jobQueue } from '@/common/jobs'` | 长时间任务 |
| **缓存服务** | `import { cache } from '@/common/cache'` | 分布式缓存 |
| **数据库** | `import { prisma } from '@/config/database'` | 数据库操作 |
| **LLM能力** | `import { LLMFactory } from '@/common/llm'` | LLM调用 |
---
### 鉁?姝g‘绀轰緥锛氫娇鐢ㄥ钩鍙版湇鍔?
### ✅ 正确示例:使用平台服务
```typescript
// backend/src/modules/asl/services/literatureService.ts
import { storage } from '@/common/storage'
@@ -54,7 +58,8 @@ export class LiteratureService {
// 2. 使用平台日志系统
logger.info('PDF uploaded', { projectId, url })
// 3. 浣跨敤骞冲彴鏁版嵁搴? const literature = await prisma.aslLiterature.create({
// 3. 使用平台数据库
const literature = await prisma.aslLiterature.create({
data: { projectId, pdfUrl: url, pdfFileSize: pdfBuffer.length }
})
@@ -65,7 +70,8 @@ export class LiteratureService {
}
async startScreening(projectId: string, literatureIds: string[]) {
// 5. 浣跨敤骞冲彴寮傛<EFBFBD>浠诲姟锛堥暱鏃堕棿浠诲姟蹇呴』寮傛<EFBFBD>锛? const job = await jobQueue.push('asl:screening', {
// 5. 使用平台异步任务(长时间任务必须异步)
const job = await jobQueue.push('asl:screening', {
projectId,
literatureIds
})
@@ -78,44 +84,54 @@ export class LiteratureService {
---
### 鉂?閿欒<E996BF>绀轰緥锛氶噸澶嶅疄鐜板钩鍙拌兘鍔?
### ❌ 错误示例:重复实现平台能力
```typescript
// 鉂?閿欒<E996BF>锛氬湪涓氬姟妯″潡涓<E6BDA1>嚜宸卞疄鐜板瓨鍌?// backend/src/modules/asl/storage/LocalStorage.ts 鈫?涓嶅簲璇ュ瓨鍦<E793A8>
// ❌ 错误:在业务模块中自己实现存储
// backend/src/modules/asl/storage/LocalStorage.ts ← 不应该存在!
import fs from 'fs'
export class LocalStorage {
async upload(file: Buffer) {
await fs.writeFile('./uploads/file.pdf', file) // 鉂?閲嶅<E996B2>瀹炵幇
await fs.writeFile('./uploads/file.pdf', file) // ❌ 重复实现
return '/uploads/file.pdf'
}
}
// 鉂?閿欒<E996BF>锛氬湪涓氬姟妯″潡涓<E6BDA1>嚜宸卞疄鐜版棩蹇?// backend/src/modules/asl/logger/logger.ts 鈫?涓嶅簲璇ュ瓨鍦<E793A8>
// ❌ 错误:在业务模块中自己实现日志
// backend/src/modules/asl/logger/logger.ts ← 不应该存在!
import winston from 'winston'
export const logger = winston.createLogger({...}) // 鉂?閲嶅<E996B2>瀹炵幇
export const logger = winston.createLogger({...}) // ❌ 重复实现
// 鉂?閿欒<E996BF>锛氭瘡娆℃柊寤烘暟鎹<E69A9F>簱杩炴帴
// ❌ 错误:每次新建数据库连接
import { PrismaClient } from '@prisma/client'
export function getUser() {
const prisma = new PrismaClient() // 鉂?杩炴帴娉勬紡
const prisma = new PrismaClient() // ❌ 连接泄漏
return prisma.user.findMany()
}
```
**为什么错误?**
- 鉂?閲嶅<E996B2>爜锛岄毦浠ョ淮鎶?- 鉂?涓嶅悓妯″潡瀹炵幇涓嶄竴鑷?- 鉂?鏃犳硶缁熶竴鍒囨崲鐜<E5B4B2><E9909C>锛堟湰鍦?浜戠<E6B59C>锛?- 鉂?娴<>垂寮€鍙戞椂闂?- 鉂?浜戠<E6B59C>閮ㄧ讲浼氬け璐ワ紙Serverless闄愬埗锛?
- ❌ 重复代码,难以维护
- ❌ 不同模块实现不一致
- ❌ 无法统一切换环境(本地/云端)
- ❌ 浪费开发时间
- ❌ 云端部署会失败Serverless限制
---
### 文件上传规范
```typescript
// 鉁?姝g‘锛氫娇鐢ㄥ瓨鍌ㄦ娊璞″眰
// ✅ 正确:使用存储抽象层
const url = await storage.upload('asl/pdf/123.pdf', buffer)
// 鉂?閿欒<E996BF>锛氱洿鎺ユ搷浣滄枃浠剁郴缁?fs.writeFileSync('./uploads/123.pdf', buffer) // Serverless瀹瑰櫒閲嶅惎浼氫涪澶?
// 鉂?閿欒<E996BF>锛氱‖缂栫爜瀛樺偍璺<E5818D>
// ❌ 错误:直接操作文件系统
fs.writeFileSync('./uploads/123.pdf', buffer) // Serverless容器重启会丢失
// ❌ 错误:硬编码存储路径
const filePath = 'D:/uploads/123.pdf' // Windows路径Linux无法运行
```
@@ -124,7 +140,7 @@ const filePath = 'D:/uploads/123.pdf' // Windows路径Linux无法运行
### 异步任务规范
```typescript
// 鉁?姝g‘锛氶暱鏃堕棿浠诲姟锛?10绉掞級蹇呴』寮傛<E5AFAE>澶勭悊
// ✅ 正确:长时间任务(>10秒必须异步处理
app.post('/screening/start', async (req, res) => {
const job = await jobQueue.push('asl:screening', data)
res.send({ jobId: job.id }) // 立即返回,不等待完成
@@ -136,26 +152,29 @@ app.get('/screening/jobs/:id', async (req, res) => {
res.send({ status: job.status, progress: job.progress })
})
// 鉂?閿欒<E996BF>锛氬悓姝ョ瓑寰呴暱鏃堕棿浠诲姟
// ❌ 错误:同步等待长时间任务
app.post('/screening/start', async (req, res) => {
const results = await processAllLiteratures(data) // <EFBFBD>兘闇€瑕?0鍒嗛挓
const results = await processAllLiteratures(data) // 可能需要10分钟
res.send({ results }) // Serverless 30秒超时
})
```
---
### 鏁版嵁搴撹繛鎺ヨ<EFBFBD>鑼?
### 数据库连接规范
```typescript
// 鉁?姝g‘锛氫娇鐢ㄥ叏灞€Prisma瀹炰緥
// ✅ 正确:使用全局Prisma实例
import { prisma } from '@/config/database'
export async function getUsers() {
return await prisma.user.findMany()
}
// 鉂?閿欒<E996BF>锛氭瘡娆℃柊寤哄疄渚?export async function getUsers() {
const prisma = new PrismaClient() // 杩炴帴鏁拌€楀敖锛? return await prisma.user.findMany()
// ❌ 错误:每次新建实例
export async function getUsers() {
const prisma = new PrismaClient() // 连接数耗尽!
return await prisma.user.findMany()
}
```
@@ -164,44 +183,52 @@ export async function getUsers() {
### 日志规范
```typescript
// 鉁?姝g‘锛氫娇鐢ㄥ钩鍙版棩蹇楃郴缁?import { logger } from '@/common/logging'
// ✅ 正确:使用平台日志系统
import { logger } from '@/common/logging'
logger.info('Operation successful', { userId, action: 'upload' })
logger.error('Operation failed', { error: err.message, userId })
// 鉂?閿欒<E996BF>锛氫娇鐢╟onsole.log
console.log('Operation successful') // 鏃犳硶闆嗕腑鏀堕泦锛岄毦浠ユ煡璇?
// 鉂?閿欒<E996BF>锛氬啓鏈<E59593>湴鏃ュ織鏂囦欢
fs.appendFileSync('./app.log', 'Operation successful') // Serverless涓嶆敮鎸?```
// ❌ 错误使用console.log
console.log('Operation successful') // 无法集中收集,难以查询
// ❌ 错误:写本地日志文件
fs.appendFileSync('./app.log', 'Operation successful') // Serverless不支持
```
---
## 通用规范
### 代码风格
- ?ESLint鍜孭rettier缁熶竴浠g爜椋庢牸
- ??<EFBFBD>?- ?<EFBFBD>?`'`
- ?<EFBFBD>?- ?<EFBFBD>ч100<EFBFBD>
- ?彿<EFBFBD>°
- ✅ 使用ESLint和Prettier统一代码风格
- ✅ 缩进2个空格
- ✅ 字符串:优先使用单引号 `'`
- ✅ 行尾:不加分号(除非必要)
- ✅ 单行最大长度100字符
- ✅ 使用尾随逗号(对象、数组)
### 文件组织
- ?<EFBFBD><EFBFBD>??- ?稿<EFBFBD>
- ?barrel exports锛坕ndex.ts锛?- ??
- ✅ 一个文件一个组件/类
- ✅ 相关文件放在同一目录
- ✅ 使用barrel exportsindex.ts
- ✅ 测试文件与源文件同目录
```
src/
├── components/
鈹? 鈹溾攢鈹€ Button/
鈹? 鈹? 鈹溾攢鈹€ Button.tsx
鈹? 鈹? 鈹溾攢鈹€ Button.test.tsx
鈹? 鈹? 鈹溾攢鈹€ Button.styles.ts
鈹? 鈹? 鈹斺攢鈹€ index.ts # export { Button } from './Button'
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.test.tsx
│ │ ├── Button.styles.ts
│ │ └── index.ts # export { Button } from './Button'
```
### 代码注释
- 鉁?澶嶆潅閫昏緫蹇呴』娉ㄩ噴
- 鉁?鍏<>叡API蹇呴』娉ㄩ噴
- 鉁?閬垮厤鏃犵敤娉ㄩ噴
- 鉁?浣跨敤JSDoc鏍煎紡
- ✅ 复杂逻辑必须注释
- ✅ 公共API必须注释
- ✅ 避免无用注释
- ✅ 使用JSDoc格式
---
@@ -209,7 +236,7 @@ src/
### 类型定义
**鉁?鎺ㄨ崘锛?*
**✅ 推荐:**
```typescript
// 使用interface定义对象结构
interface User {
@@ -228,14 +255,16 @@ enum UserRole {
}
```
**鉂?閬垮厤锛?*
**❌ 避免:**
```typescript
// 不要使用any
function process(data: any) { // 鉂? // ...
function process(data: any) { //
// ...
}
// 应该明确类型
function process(data: ProcessData) { // 鉁? // ...
function process(data: ProcessData) { //
// ...
}
```
@@ -274,7 +303,7 @@ import type { Project, ProjectStatus } from './types'
### 组件定义
**鉁?鎺ㄨ崘锛氬嚱鏁扮粍浠?+ Hooks**
**✅ 推荐:函数组件 + Hooks**
```tsx
import { useState } from 'react'
@@ -314,14 +343,15 @@ export function Button({
}
```
**鉂?閬垮厤锛氱被缁勪欢**
**❌ 避免:类组件**
```tsx
// 除非有特殊需求,否则不使用类组件
class Button extends React.Component { ... } // 鉂?```
class Button extends React.Component { ... } //
```
### Hooks规范
**?Hooks**
**✅ 推荐自定义Hooks**
```typescript
// useProjects.ts
import { useState, useEffect } from 'react'
@@ -373,7 +403,8 @@ function ProjectList() {
### 组件组织
```tsx
// 鉁?鎺ㄨ崘鐨勭粍浠剁粨鏋?import { useState, useEffect, useMemo, useCallback } from 'react'
// ✅ 推荐的组件结构
import { useState, useEffect, useMemo, useCallback } from 'react'
import { useNavigate } from 'react-router-dom'
import { SomeComponent } from '@/components'
import { useCustomHook } from '@/hooks'
@@ -389,19 +420,23 @@ export function Component({ prop1, prop2 }: ComponentProps) {
const [state, setState] = useState()
const { data } = useCustomHook()
// 2. 娲剧敓鐘舵€侊紙useMemo锛? const computedValue = useMemo(() => {
// 2. 派生状态useMemo
const computedValue = useMemo(() => {
return heavyComputation(data)
}, [data])
// 3. 浜嬩欢澶勭悊锛坲seCallback锛? const handleClick = useCallback(() => {
// 3. 事件处理(useCallback
const handleClick = useCallback(() => {
// 处理逻辑
}, [])
// 4. Effects
useEffect(() => {
// <EFBFBD>綔鐢? }, [])
// 副作用
}, [])
// 5. 鏃╂湡杩斿洖锛圠oading/Error锛? if (!data) return <Loading />
// 5. 早期返回Loading/Error
if (!data) return <Loading />
// 6. 渲染
return (
@@ -414,7 +449,7 @@ export function Component({ prop1, prop2 }: ComponentProps) {
### 条件渲染
**鉁?鎺ㄨ崘锛?*
**✅ 推荐:**
```tsx
// 简单条件:使用 &&
{isLoggedIn && <UserMenu />}
@@ -433,14 +468,14 @@ function renderContent() {
return <div>{renderContent()}</div>
```
**鉂?閬垮厤锛?*
**❌ 避免:**
```tsx
// 避免复杂的嵌套三元运算符
{condition1 ? (
condition2 ? <A /> : <B />
) : (
condition3 ? <C /> : <D />
)} // 鉂?闅句互鐞嗚В
)} // ❌ 难以理解
```
---
@@ -452,11 +487,11 @@ return <div>{renderContent()}</div>
```
backend/src/
├── routes/ # 路由定义
鈹? 鈹溾攢鈹€ auth.routes.ts
鈹? 鈹斺攢鈹€ project.routes.ts
│ ├── auth.routes.ts
│ └── project.routes.ts
├── services/ # 业务逻辑
鈹? 鈹溾攢鈹€ auth.service.ts
鈹? 鈹斺攢鈹€ project.service.ts
│ ├── auth.service.ts
│ └── project.service.ts
├── controllers/ # 控制器(可选)
├── models/ # Prisma模型
├── utils/ # 工具函数
@@ -536,7 +571,8 @@ export async function projectRoutes(server: FastifyInstance) {
}
```
### Service灞?
### Service
```typescript
// services/project.service.ts
import { prisma } from '../lib/prisma'
@@ -544,7 +580,8 @@ import type { CreateProjectDto, UpdateProjectDto } from '../types'
export class ProjectService {
/**
* 鑾峰彇鐢ㄦ埛鐨勯」鐩<EFBFBD>垪琛? */
* 获取用户的项目列表
*/
async getProjects(userId: string, options: PaginationOptions) {
const { page, pageSize } = options
@@ -675,7 +712,8 @@ async function getProject(id: string) {
}
```
### 閿欒<EFBFBD>澶勭悊涓<EFBFBD>棿浠?
### 错误处理中间件
```typescript
// middleware/error-handler.ts
import { FastifyError, FastifyReply, FastifyRequest } from 'fastify'
@@ -689,7 +727,8 @@ export async function errorHandler(
// 记录错误
request.log.error(error)
// <EFBFBD>畾涔夐敊璇? if (error instanceof AppError) {
// 自定义错误
if (error instanceof AppError) {
return reply.code(error.statusCode).send({
success: false,
error: {
@@ -744,22 +783,23 @@ export async function errorHandler(
### 变量命名
```typescript
// 鉁?鎺ㄨ崘
// ✅ 推荐
const userName = 'John' // camelCase
const USER_ROLE = 'admin' // 常量用UPPER_SNAKE_CASE
const isLoading = false // 布尔值用is/has/can前缀
const hasPermission = true
const canEdit = false
// 鉂?閬垮厤
// ❌ 避免
const user_name = 'John' // 不用snake_case
const loading = false // 布尔值缺少is前缀
const x = 10 // 鏃犳剰涔夌殑鍙橀噺鍚?```
const x = 10 // 无意义的变量名
```
### 函数命名
```typescript
// 鉁?鎺ㄨ崘
// ✅ 推荐
function getUser() { } // get: 获取数据
function fetchProjects() { } // fetch: 异步获取
function createProject() { } // create: 创建
@@ -767,20 +807,24 @@ function updateProject() { } // update: 更新
function deleteProject() { } // delete: 删除
function handleClick() { } // handle: 事件处理
function validateEmail() { } // validate: 验证
function formatDate() { } // format: 鏍煎紡鍖?
// 鉂?閬垮厤
function data() { } // 涓嶆竻妤氬姛鑳?function doSomething() { } // 澶<>ā绯?function process() { } // 涓嶆槑纭?```
function formatDate() { } // format: 格式化
// ❌ 避免
function data() { } // 不清楚功能
function doSomething() { } // 太模糊
function process() { } // 不明确
```
### 组件命名
```typescript
// 鉁?鎺ㄨ崘
// ✅ 推荐
<Button /> // 基础组件
<UserProfile /> // 业务组件
<ProjectList /> // 列表组件
<CreateProjectModal /> // 弹窗组件
// 鉂?閬垮厤
// ❌ 避免
<button /> // 不用小写
<user_profile /> // 不用snake_case
<ListProjects /> // 动词不要在前
@@ -794,9 +838,11 @@ function data() { } // 不清楚功
```typescript
/**
* 鍒涘缓鏂伴」鐩? * @param userId - 鐢ㄦ埛ID
* 创建新项目
* @param userId - 用户ID
* @param data - 项目数据
* @returns 鍒涘缓鐨勯」鐩<EFBFBD><EFBFBD>璞? * @throws {ValidationError} 褰撴暟鎹<E69A9F>獙璇佸け璐ユ椂
* @returns 创建的项目对象
* @throws {ValidationError} 当数据验证失败时
*/
async function createProject(
userId: string,
@@ -809,18 +855,21 @@ async function createProject(
### 代码注释
```typescript
// 鉁?濂界殑娉ㄩ噴锛氳В閲婁负浠€涔?// 浣跨敤setTimeout閬垮厤闃诲<E99783>UI娓叉煋
// ✅ 好的注释:解释为什么
// 使用setTimeout避免阻塞UI渲染
setTimeout(() => {
processLargeData()
}, 0)
// 绛夊緟Dify澶勭悊鏂囨。锛屾渶澶氶噸璇?0娆?for (let i = 0; i < 10; i++) {
// 等待Dify处理文档最多重试10次
for (let i = 0; i < 10; i++) {
const status = await checkStatus()
if (status === 'completed') break
await sleep(2000)
}
// 鉂?鍧忕殑娉ㄩ噴锛氶噸澶嶄唬鐮?// 璁剧疆loading涓簍rue
// ❌ 坏的注释:重复代码
// 设置loading为true
setLoading(true)
// 调用API
@@ -845,10 +894,10 @@ await api.getData()
| 类型 | 说明 |
|------|------|
| feat | 鏂板姛鑳?|
| feat | 新功能 |
| fix | Bug修复 |
| docs | 文档更新 |
| style | 浠g爜鏍煎紡锛堜笉褰卞搷鍔熻兘锛?|
| style | 代码格式(不影响功能) |
| refactor | 重构 |
| perf | 性能优化 |
| test | 测试相关 |
@@ -863,8 +912,11 @@ git commit -m "fix(project): 修复项目删除权限问题"
git commit -m "docs(api): 更新API文档"
git commit -m "refactor(chat): 优化消息组件结构"
# 涓嶅ソ鐨勬彁浜?git commit -m "update" # 鉂?澶<>ā绯?git commit -m "fix bug" # 鉂?娌℃湁璇存槑鏄<E6A791>粈涔坆ug
git commit -m "瀹屾垚鍔熻兘" # 鉂?娌℃湁璇存槑鏄<E6A791>粈涔堝姛鑳?```
# 不好的提交
git commit -m "update" # ❌ 太模糊
git commit -m "fix bug" # ❌ 没有说明是什么bug
git commit -m "完成功能" # ❌ 没有说明是什么功能
```
---
@@ -907,30 +959,36 @@ module.exports = {
---
## 浠g爜Review妫€鏌ユ竻鍗?
## 代码Review检查清单
### 功能
- [ ] 功能是否完整实现
- [ ] 是否有遗漏的边界情况
- [ ] 错误处理是否完善
### 代码质量
- [ ] 爜鏄<EFBFBD>惁鏄撹<EFBFBD>鏄撶悊瑙?- [ ] 鏄<>惁鏈夐噸澶嶄唬鐮?- [ ] 鍑芥暟鏄<E69A9F>惁杩囬暱锛堝缓璁?50琛岋級
- [ ] 代码是否易读易理解
- [ ] 是否有重复代码
- [ ] 函数是否过长(建议<50行
- [ ] 是否遵守命名规范
### 性能
- [ ] 是否有性能问题
- [ ] 是否有不必要的重渲染
- [ ] 鏁版嵁搴撴煡璇㈡槸鍚︿紭鍖?
- [ ] 数据库查询是否优化
### 安全
- [ ] 是否有SQL注入风险
- [ ] 是否有XSS风险
- [ ] 权限验证是否完善
### 测试
- [ ] <EFBFBD>惁鏈夊崟鍏冩祴璇?- [ ] 娴嬭瘯瑕嗙洊鐜囨槸鍚﹁冻澶?
- [ ] 是否有单元测试
- [ ] 测试覆盖率是否足够
---
**鏂囨。缁存姢锛?* 瑙勮寖鏇存柊闇€鍚屾<E98D9A>姝ゆ枃妗?
**文档维护:** 规范更新需同步此文档
**最后更新:** 2025-10-10
**维护者:** 技术负责人

File diff suppressed because it is too large Load Diff

View File

@@ -1,42 +1,47 @@
# 鈭穃<EFBFBD><EFBFBD><EFBFBD><EFBFBD>𤏸<EFBFBD><EFBFBD>?
> **<2A><><EFBFBD><EFB99D>𧋦嚗?* V1.1
> **<EFBFBD>𥕦遣<EFBFBD><EFBFBD>嚗?* 2025-11-16
# 云原生开发规范
> **文档版本:** V1.1
> **创建日期:** 2025-11-16
> **最后更新:** 2025-12-13 🏆 **Postgres-Only 架构规范新增**
> **<EFBFBD><EFBFBD>鍂撖寡情嚗?* <20><><EFBFBD><EFBFBD><E58CA7>睲犖<E79DB2>?
> **撘箏<EFBFBD><EFBFBD><EFBFBD>** <20>?敹<><EFBFBD><EFBFBD>
> **适用对象:** 所有开发人员
> **强制性:** ✅ 必须遵守
> **维护者:** 架构团队
---
## 📋 文档说明
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>銋劐<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗𠄎erverless SAE + RDS + OSS嚗劐<EFBFBD><EFBFBD>?*隞<><E99A9E><EFBFBD><E996AB>**嚗峕<E59A97><E5B395><EFBFBD><E58A90>⊥芋<E28AA5><EFBFBD>ASL<53><4C>IA<49><41>KB蝑㚁<E89D91><EFBFBD><EFBFBD><EFBFBD><E89084>?
**<EFBFBD><EFBFBD><EFBFBD>園𡢿**嚗?0 <20><><EFBFBD>
**<EFBFBD><EFBFBD>仿<EFBFBD><EFBFBD>?*嚗𡁏<E59A97>甈∩誨<E288A9><E8AAA8><EFBFBD>鈭文<E988AD>
本文档定义云原生环境Serverless SAE + RDS + OSS)下的**代码规范**所有业务模块ASL、AIA、PKB等必须遵守。
**阅读时间**10 分钟
**检查频率**:每次代码提交前
---
## <EFBFBD><EFBFBD> <20><EFBFBD><E8A9A8><EFBFBD>嚗𡁜<E59A97><F0A1819C>典像<E585B8><EFBFBD><E59597>?
> **潃?<3F><EFBFBD><E6BBA9>鞟內嚗?025-11-16 <20>湔鰵嚗?*嚗𡁜像<F0A1819C>啣歇<E595A3>𣂷<EFBFBD>摰峕㟲<E5B395><E39FB2>抅蝖<E68A85>霈暹鴌<E69AB9>滚𦛚
## 🌟 核心原则:复用平台能力
> **⭐ 重要提示2025-11-16 更新)**:平台已提供完整的基础设施服务
> **详细文档**[平台基础设施规划](../09-架构实施/04-平台基础设施规划.md)
### 平台已提供的服务
**业务模块ASL/AIA/PKB/DC等应该复用以下平台能力禁止重复实现**
| <EFBFBD>滚𦛚 | 撖澆<E69296><E6BE86><EFBFBD> | <20><EFBFBD>?| <20><> |
| 服务 | 导入方式 | 用途 | 文档 |
|------|---------|------|------|
| **摮睃<EFBFBD><EFBFBD>滚𦛚** | `import { storage } from '@/common/storage'` | <EFBFBD><EFBFBD>辣銝𠹺<EFBFBD>銝贝蝸 | <20>?撟喳蝱蝥?|
| **<EFBFBD><EFBFBD>蝟餌<EFBFBD>** | `import { logger } from '@/common/logging'` | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>𡝗𠯫敹?| <20>?撟喳蝱蝥?|
| **<EFBFBD>郊隞餃𦛚** | `import { jobQueue } from '@/common/jobs'` | <EFBFBD>踵𧒄<EFBFBD>港遙<EFBFBD>?| <20>?撟喳蝱蝥?|
| **蝻枏<EFBFBD><EFBFBD>滚𦛚** | `import { cache } from '@/common/cache'` | <EFBFBD><EFBFBD><EFBFBD>撘讐<EFBFBD>摮?| <20>?撟喳蝱蝥?|
| **<EFBFBD><EFBFBD> <20><EFBFBD>蝏凋<E89D8F>** | `import { CheckpointService } from '@/common/jobs'` | 隞餃𦛚<EFBFBD><EFBFBD>蝞∠<EFBFBD> | <20>?撟喳蝱蝥改<E89DA5><E694B9><EFBFBD> |
| **<EFBFBD>唳旿摨?* | `import { prisma } from '@/config/database'` | <EFBFBD>唳旿摨𤘪<EFBFBD>雿?| <20>?撟喳蝱蝥?|
| **LLM<EFBFBD><EFBFBD>** | `import { LLMFactory } from '@/common/llm'` | LLM<EFBFBD>鍂 | <20>?撟喳蝱蝥?|
| **存储服务** | `import { storage } from '@/common/storage'` | 文件上传下载 | ✅ 平台级 |
| **日志系统** | `import { logger } from '@/common/logging'` | 标准化日志 | ✅ 平台级 |
| **异步任务** | `import { jobQueue } from '@/common/jobs'` | 长时间任务 | ✅ 平台级 |
| **缓存服务** | `import { cache } from '@/common/cache'` | 分布式缓存 | ✅ 平台级 |
| **🏆 断点续传** | `import { CheckpointService } from '@/common/jobs'` | 任务断点管理 | ✅ 平台级(新) |
| **数据库** | `import { prisma } from '@/config/database'` | 数据库操作 | ✅ 平台级 |
| **LLM能力** | `import { LLMFactory } from '@/common/llm'` | LLM调用 | ✅ 平台级 |
### 示例:正确使用平台服务
### 蝷箔<E89DB7>嚗𡁏迤蝖桐蝙<E6A190>典像<E585B8><EFBFBD><E594B3>?
```typescript
// <EFBFBD>?甇<>嚗𡁶凒<F0A181B6>亙紡<E4BA99>亙像<E4BA99><EFBFBD><E594B3>?import { storage } from '@/common/storage'
// ✅ 正确:直接导入平台服务
import { storage } from '@/common/storage'
import { logger } from '@/common/logging'
import { jobQueue } from '@/common/jobs'
import { prisma } from '@/config/database'
@@ -50,7 +55,8 @@ export class LiteratureService {
// 2. 使用平台日志系统
logger.info('PDF uploaded', { projectId, url })
// 3. 雿輻鍂撟喳蝱<EFBFBD>唳旿摨? const literature = await prisma.aslLiterature.create({
// 3. 使用平台数据库
const literature = await prisma.aslLiterature.create({
data: { projectId, pdfUrl: url }
})
@@ -59,26 +65,36 @@ export class LiteratureService {
}
```
### <EFBFBD>?<3F>躰秤嚗𡁻<E59A97>憭滚<E686AD><E6BB9A>啣像<E595A3><EFBFBD><E59597>?
### ❌ 错误:重复实现平台能力
```typescript
// <EFBFBD>?<3F>躰秤嚗𡁜銁銝𡁜𦛚璅<E79285>銝剛䌊撌勗<E6928C><E58B97><EFBFBD><E595A3>?// backend/src/modules/asl/storage/LocalStorage.ts <20>?銝滚<E98A9D>霂亙<E99C82><E4BA99><EFBFBD>
// ❌ 错误:在业务模块中自己实现存储
// backend/src/modules/asl/storage/LocalStorage.ts ← 不应该存在!
export class LocalStorage {
async upload(file: Buffer) {
await fs.writeFile('./uploads/file.pdf', file) // <EFBFBD>?<3F><EFBFBD>摰䂿緵
await fs.writeFile('./uploads/file.pdf', file) // ❌ 重复实现
}
}
// <EFBFBD>?<3F>躰秤嚗𡁜銁銝𡁜𦛚璅<E79285>銝剛䌊撌勗<E6928C><E58B97>唳𠯫敹?// backend/src/modules/asl/logger/logger.ts <20>?銝滚<E98A9D>霂亙<E99C82><E4BA99><EFBFBD>
export const logger = winston.createLogger({...}) // <20>?<3F><EFBFBD>摰䂿緵
// ❌ 错误:在业务模块中自己实现日志
// backend/src/modules/asl/logger/logger.ts ← 不应该存在!
export const logger = winston.createLogger({...}) // ❌ 重复实现
```
**<EFBFBD><EFBFBD>**嚗?- <20>?<3F><EFBFBD><EFBFBD><E99A9E>嚗屸𠗕隞亦輕<E4BAA6>?- <20>?銝滚<E98A9D><E79285>摰䂿緵銝滢<E98A9D><E6BBA2>?- <20>?<3F><EFBFBD>蝏煺<E89D8F><E785BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>𧋦<EFBFBD>?鈭𤑳垢嚗?- <20>?瘚芾晶撘<E699B6><E69298>烐𧒄<E78390>?
**原因**
- ❌ 重复代码,难以维护
- ❌ 不同模块实现不一致
- ❌ 无法统一切换环境(本地/云端)
- ❌ 浪费开发时间
---
## <EFBFBD>?<3F><EFBFBD><E588BB>𡁏<EFBFBD>嚗㇄O嚗?
### 1. <20><>辣摮睃<E691AE> <20>?
## ✅ 推荐做法DO
### 1. 文件存储 ✅
```typescript
// <EFBFBD>?甇<>嚗帋蝙<E5B88B><EFBFBD><E585B8>冽𡂝鞊<E99E8A>
// ✅ 正确:使用存储抽象层
import { storage } from '@/common/storage/StorageFactory'
export async function uploadFile(file: Buffer, filename: string) {
@@ -87,7 +103,8 @@ export async function uploadFile(file: Buffer, filename: string) {
return url
}
// <EFBFBD>?甇<>嚗鍃xcel <20>湔𦻖隞𤾸<E99A9E>摮䁅圾<E48185>?import * as xlsx from 'xlsx'
// ✅ 正确Excel 直接从内存解析
import * as xlsx from 'xlsx'
export async function importExcel(buffer: Buffer) {
const workbook = xlsx.read(buffer, { type: 'buffer' }) // 内存解析
@@ -96,35 +113,42 @@ export async function importExcel(buffer: Buffer) {
}
```
**<EFBFBD><EFBFBD>眏**嚗?- 摰孵膥<E5ADB5>滚鍳銝滢<E98A9D><EFBCB7><E4BB83>
- <EFBFBD>砍𧑐撘<EFBFBD><EFBFBD><EFBFBD><EFBFBD>煺漣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?- <20>芸𢆡<E88AB8>寞旿<E5AF9E><EFBFBD><E887AC><EFBFBD><E3979B><EFBFBD>揢摮睃<E691AE><E79D83><EFBFBD>
**理由**
- 容器重启不会丢失文件
- 本地开发和生产环境代码一致
- 自动根据环境变量切换存储方式
---
### 2. <EFBFBD>唳旿摨栞<EFBFBD><EFBFBD>?<3F>?
### 2. 数据库连接 ✅
```typescript
// <EFBFBD>?甇<>嚗帋蝙<E5B88B><EFBFBD><EFBFBD> Prisma Client
// ✅ 正确:使用全局 Prisma Client
import { prisma } from '@/config/database'
export async function createProject(data: any) {
return await prisma.aslScreeningProject.create({ data })
}
// <EFBFBD>?甇<>嚗𡁏鸌<F0A1818F>𤩺<EFBFBD>雿靝蝙<E99D9D><EFBFBD><E585B6>?export async function importLiteratures(literatures: any[]) {
// ✅ 正确:批量操作使用事务
export async function importLiteratures(literatures: any[]) {
return await prisma.$transaction(async (tx) => {
return await tx.aslLiterature.createMany({ data: literatures })
})
}
```
**<EFBFBD><EFBFBD>眏**嚗?- <20><EFBFBD>摰硺<E691B0>憭滨鍂餈墧𦻖
**理由**
- 全局实例复用连接
- 避免连接数耗尽
- 鈭见𦛚靽肽<EFBFBD><EFBFBD>唳旿銝<EFBFBD><EFBFBD><EFBFBD>?
- 事务保证数据一致性
---
### 3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滨蔭 <20>?
### 3. 环境变量配置 ✅
```typescript
// <EFBFBD>?甇<>嚗𡁶<E59A97><EFBFBD><E98A9D>滨蔭蝞∠<E89D9E>
// ✅ 正确:统一配置管理
// backend/src/config/env.ts
export const config = {
llm: {
@@ -140,19 +164,22 @@ export const config = {
}
}
// <EFBFBD>?甇<>嚗帋蝙<E5B88B><EFBFBD>蝵桀笆鞊?import { config } from '@/config/env'
// ✅ 正确:使用配置对象
import { config } from '@/config/env'
const apiKey = config.llm.apiKey
```
**<EFBFBD><EFBFBD>眏**嚗?- <20>滨蔭<E6BBA8><E894AD>葉蝞∠<E89D9E>
**理由**
- 配置集中管理
- 类型安全
- 便于切换环境
---
### 4. <EFBFBD>踵𧒄<EFBFBD>港遙<EFBFBD><EFBFBD><EFBFBD>?<3F>?
### 4. 长时间任务处理 ✅
```typescript
// <EFBFBD>?甇<>嚗𡁜<E59A97>甇乩遙<E4B9A9>?+ 餈𥕦漲頧株砭
// ✅ 正确:异步任务 + 进度轮询
export async function startScreening(req, res) {
// 1. 创建任务记录
const task = await prisma.aslScreeningTask.create({
@@ -166,8 +193,9 @@ export async function startScreening(req, res) {
// 2. 立即返回任务ID
res.send({ success: true, taskId: task.id })
// 3. <EFBFBD>𤾸蝱撘<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>霂瑟<EFBFBD>嚗? processScreeningAsync(task.id).catch(err => {
console.error('蝑偦<E89D91>劐遙<E58A90>仃韐?', err)
// 3. 后台异步执行(不阻塞请求)
processScreeningAsync(task.id).catch(err => {
console.error('筛选任务失败:', err)
})
}
@@ -184,16 +212,20 @@ export async function getTaskProgress(req, res) {
}
```
**<EFBFBD><EFBFBD>眏**嚗?- <20><EFBFBD>霂瑟<E99C82><EFBFBD>𧒄嚗𠄎AE暺䁅恕30蝘𡜐<E89D98>
**理由**
- 避免请求超时SAE默认30秒
- 用户体验更好
- 支持批量任务
**<EFBFBD>?摰峕㟲摰噼殿<E599BC><E6AEBF><EFBFBD>?*嚗?霂西<E99C82> [Postgres-Only撘<79>郊隞餃𦛚憭<F0A69B9A><E686AD><EFBFBD><EFBFBD><EFBFBD>](../02-<2D>𡁶鍂<F0A181B6><EFBFBD>撅?Postgres-Only撘<79>郊隞餃𦛚憭<F0A69B9A><E686AD><EFBFBD><EFBFBD><EFBFBD>.md)嚗<>抅鈭𥟠C Tool C摰峕㟲摰噼殿嚗?
**✨ 完整实践参考**
详见 [Postgres-Only异步任务处理指南](../02-通用能力层/Postgres-Only异步任务处理指南.md)基于DC Tool C完整实践
---
### 5. <EFBFBD><EFBFBD>颲枏枂 <20>?
### 5. 日志输出 ✅
```typescript
// <EFBFBD>?甇<>嚗帋蝙<E5B88B>?logger 颲枏枂<EFBFBD>?stdout
// ✅ 正确:使用 logger 输出到 stdout
import pino from 'pino'
const logger = pino({
@@ -209,7 +241,7 @@ export async function uploadFile(req, res) {
// ... 上传逻辑
}
// <EFBFBD>?甇<>嚗𡁶<E59A97><F0A181B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// ✅ 正确:结构化日志
logger.error({
error: err.message,
stack: err.stack,
@@ -217,13 +249,17 @@ logger.error({
}, 'Upload failed')
```
**<EFBFBD><EFBFBD>眏**嚗?- SAE <20>芸𢆡<E88AB8><F0A286A1><EFBFBD> stdout <20><EFBFBD>
- 蝏𤘪<EFBFBD><EFBFBD>碶噶鈭擧䰻霂<EFBFBD><EFBFBD>?- <20><><EFBFBD><EFBFBD>嚗䔶<E59A97>隡帋腺憭?
**理由**
- SAE 自动采集 stdout 日志
- 结构化便于查询分析
- 集中查看,不会丢失
---
### 6. <EFBFBD>躰秤憭<EFBFBD><EFBFBD> <20>?
### 6. 错误处理 ✅
```typescript
// <EFBFBD>?甇<>嚗𡁶<E59A97><EFBFBD><E98A9D>躰秤憭<E7A7A4><E686AD>
// ✅ 正确:统一错误处理
export async function uploadPdf(req, res) {
try {
const file = await req.file()
@@ -246,14 +282,17 @@ export async function uploadPdf(req, res) {
}
```
**<EFBFBD><EFBFBD>眏**嚗?- <20><EFBFBD><E586BD><EFBFBD><E8A781>见末<E8A781>躰秤靽⊥<E99DBD>
**理由**
- 用户看到友好错误信息
- 日志记录详细错误
- 銝齿𠂔<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
- 不暴露内部实现
---
### 7. 銝湔𧒄<EFBFBD><EFBFBD>辣憭<EFBFBD><EFBFBD> <20>?
### 7. 临时文件处理 ✅
```typescript
// <EFBFBD>?甇<>嚗?tmp <20><EFBFBD><E6A180><EFBFBD>蝡见朖<E8A781>𣳇膄
// ✅ 正确:/tmp 目录用完立即删除
import fs from 'fs/promises'
import path from 'path'
@@ -261,7 +300,7 @@ export async function extractPdfText(ossKey: string): Promise<string> {
const tmpPath = path.join('/tmp', `${Date.now()}.pdf`)
try {
// 1. 隞?OSS 銝贝蝸<EFBFBD>?/tmp
// 1. OSS 下载到 /tmp
await storage.download(ossKey, tmpPath)
// 2. 提取文本
@@ -279,43 +318,51 @@ export async function extractPdfText(ossKey: string): Promise<string> {
}
```
**<EFBFBD><EFBFBD>眏**嚗?- /tmp 摰寥<E691B0><E5AFA5><EFBFBD>嚗?12MB嚗?- 摰孵膥<E5ADB5>滚鍳隡𡁏<E99AA1>蝛?- <20><EFBFBD><EFBFBD><E89DA4><EFBFBD>䭾說
**理由**
- /tmp 容量有限512MB
- 容器重启会清空
- 避免磁盘占满
---
## <EFBFBD><EFBFBD> Postgres-Only <EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?025-12-13 <EFBFBD><EFBFBD>嚗?
## 🏆 Postgres-Only 架构规范2025-12-13 新增)
### 核心理念
**Platform-Only <EFBFBD>**嚗𡁏<E59A97><F0A1818F>劐遙<E58A90>∠恣<E288A0><E681A3><EFBFBD><EFBFBD><EFBFBD>摮睃<E691AE><E79D83>?`platform_schema.job.data`嚗䔶<EFBFBD><EFBFBD>∟”<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>∩縑<EFBFBD><EFBFBD>?
### 隞餃𦛚蝞∠<E89D9E><E288A0><EFBFBD>迤蝖桀<E89D96>瘜?
#### <EFBFBD>?DO: 雿輻鍂 job.data 摮睃<E691AE>隞餃𦛚蝞∠<E89D9E>靽⊥<E99DBD>
**Platform-Only 模式**:所有任务管理信息统一存储在 `platform_schema.job.data`,业务表只存储业务信息。
### 任务管理的正确做法
#### ✅ DO: 使用 job.data 存储任务管理信息
```typescript
// <EFBFBD>?甇<>嚗帋遙<E5B88B><EFBFBD><E28AA5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>靽⊥<E99DBD>摮睃<E691AE><E79D83>?job.data
// ✅ 正确:任务拆分和断点信息存储在 job.data
import { jobQueue } from '@/common/jobs';
import { CheckpointService } from '@/common/jobs/CheckpointService';
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>⊥𧒄嚗<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>港縑<EFBFBD>?await jobQueue.push('asl:screening:batch', {
// 推送任务时,包含完整信息
await jobQueue.push('asl:screening:batch', {
// 业务信息
taskId: 'xxx',
projectId: 'yyy',
literatureIds: [...],
// <EFBFBD>?隞餃𦛚<E9A483><F0A69B9A><EFBFBD>靽⊥<E99DBD><EFBFBD><E59A97><EFBFBD>典銁 job.data嚗? batchIndex: 3,
// ✅ 任务拆分信息(存储在 job.data
batchIndex: 3,
totalBatches: 20,
startIndex: 150,
endIndex: 200,
// <EFBFBD>?餈𥕦漲餈質葵
// ✅ 进度追踪
processedCount: 0,
successCount: 0,
failedCount: 0,
});
// Worker 銝凋蝙<EFBFBD>?CheckpointService
// Worker 中使用 CheckpointService
const checkpointService = new CheckpointService(prisma);
// 靽嘥<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?job.data
// 保存断点到 job.data
await checkpointService.saveCheckpoint(job.id, {
currentBatchIndex: 5,
currentIndex: 250,
@@ -323,39 +370,52 @@ await checkpointService.saveCheckpoint(job.id, {
totalBatches: 20
});
// <EFBFBD>㰘蝸<EFBFBD><EFBFBD>隞?job.data
// 加载断点从 job.data
const checkpoint = await checkpointService.loadCheckpoint(job.id);
if (checkpoint) {
resumeFrom = checkpoint.currentIndex;
}
```
#### <EFBFBD>?DON'T: <EFBFBD><EFBFBD><EFBFBD>∟”銝剖<EFBFBD><EFBFBD>其遙<EFBFBD>∠恣<EFBFBD><EFBFBD><EFBFBD>?
#### DON'T: 在业务表中存储任务管理信息
```typescript
// <EFBFBD>?<3F>躰秤嚗𡁜銁銝𡁜𦛚銵函<E98AB5> Schema 銝剜溶<E5899C>牐遙<E78990>∠恣<E288A0><E681A3><EFBFBD>畾?model AslScreeningTask {
// ❌ 错误:在业务表的 Schema 中添加任务管理字段
model AslScreeningTask {
id String @id
projectId String
// <EFBFBD>?銝滩<E98A9D>瘛餃<E7989B>餈嗘<E9A488>摮埈挾嚗? totalBatches Int // <20>?摨磰砲<E7A3B0>?job.data 銝? processedBatches Int // <20>?摨磰砲<E7A3B0>?job.data 銝? currentIndex Int // <20>?摨磰砲<E7A3B0>?job.data 銝? checkpointData Json? // <20>?摨磰砲<E7A3B0>?job.data 銝?}
// ❌ 不要添加这些字段!
totalBatches Int // ← 应该在 job.data 中
processedBatches Int // ← 应该在 job.data 中
currentIndex Int // ← 应该在 job.data 中
checkpointData Json? // ← 应该在 job.data 中
}
// <EFBFBD>?<3F>躰秤嚗朞䌊撌勗<E6928C><E58B97>唳鱏<E594B3><EFBFBD><E5AF9E>?class MyCheckpointService {
// ❌ 错误:自己实现断点服务
class MyCheckpointService {
async save(taskId: string) {
await prisma.aslScreeningTask.update({
where: { id: taskId },
data: { checkpointData: {...} } // <EFBFBD>?銝滩<E98A9D>餈蹱甅<E8B9B1>𡄯<EFBFBD>
data: { checkpointData: {...} } // ❌ 不要这样做!
});
}
}
```
**为什么不对?**
- <EFBFBD>?瘥譍葵璅<E79285><E288AA><EFBFBD>瘛餃<E7989B><E9A483><EFBFBD><E8A9A8><EFBFBD><EFBFBD>畾蛛<E795BE><EFBFBD><E99A9E><EFBFBD><EFBFBD>嚗?- <20>?餈嘥<E9A488> DRY <20><EFBFBD>
- <EFBFBD>?餈嘥<E9A488> 3 撅<><EFBFBD><E6B2B2><EFBFBD><EFBFBD>?- <20>?蝏湔擪<E6B994>圈𠗕嚗<F0A09795><EFBFBD><EFBFBD><EFBFBD><E9A489><EFBFBD><EFBFBD>㺿憭𡁜<E686AD>嚗?
- ❌ 每个模块都要添加相同的字段(代码重复)
- ❌ 违反 DRY 原则
- ❌ 违反 3 层架构原则
- ❌ 维护困难(修改逻辑需要改多处)
### 智能阈值判断的规范
#### <EFBFBD>?DO: 摰䂿緵<EFBFBD><EFBFBD><EFBFBD>峕芋撘誩<EFBFBD><EFBFBD>?
#### DO: 实现智能双模式处理
```typescript
const QUEUE_THRESHOLD = 50; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
const QUEUE_THRESHOLD = 50; // 推荐阈值
export async function startTask(items: any[]) {
const useQueue = items.length >= QUEUE_THRESHOLD;
@@ -366,68 +426,84 @@ export async function startTask(items: any[]) {
await jobQueue.push('task:batch', {...});
}
} else {
// <EFBFBD>湔𦻖璅<EFBFBD>嚗𡁜<EFBFBD>隞餃𦛚嚗?50<35><EFBFBD>
processDirectly(items); // 敹恍<EFBFBD><EFBFBD>摨? }
// 直接模式:小任务(<50条
processDirectly(items); // 快速响应
}
}
```
**銝箔<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?*
- <EFBFBD>?撠譍遙<E8AD8D><E288AA><EFBFBD>摨䈑<E691A8><E48891>𣳇<EFBFBD><F0A3B387>堒辣餈<E8BEA3><E9A488>
- <EFBFBD>?憭找遙<E689BE><EFBFBD><E28ABF><EFBFBD><EFBFBD>𣈲<EFBFBD><F0A388B2><EFBFBD>寧賒隡𩤃<E99AA1>
- <EFBFBD>?<3F><EFBFBD>銝𤾸虾<F0A4BEB8><EFBFBD>批像銵?
#### <20>?DON'T: <20><><EFBFBD>劐遙<E58A90><EFBFBD>韏圈<E99F8F><E59C88>?
**为什么这样做?**
- ✅ 小任务快速响应(无队列延迟)
- ✅ 大任务高可靠(支持断点续传)
- ✅ 性能与可靠性平衡
#### ❌ DON'T: 所有任务都走队列
```typescript
// <EFBFBD>?<3F>躰秤嚗𡁜朖雿?<3F>∟扇敶蓥<E695B6>雿輻鍂<E8BCBB><EFBFBD>
// ❌ 错误即使1条记录也使用队列
export async function startTask(items: any[]) {
// 无论多少数据,都推送到队列
await jobQueue.push('task:batch', items); // <EFBFBD>?撠譍遙<E8AD8D><EFBFBD><E288A9>匧辣餈?}
await jobQueue.push('task:batch', items); // ❌ 小任务会有延迟
}
```
**为什么不对?**
- <EFBFBD>?撠譍遙<E8AD8D><EFBFBD>摨娍<E691A8><EFBFBD><E59A97><EFBFBD><EFBFBD>頧株砭<E6A0AA><EFBFBD>嚗?- <20>?瘚芾晶<E88ABE><EFBFBD><EFBFBD><E99F8F>
- <EFBFBD>?<3F><EFBFBD>雿㯄<E99BBF>撌?
### <20><><EFBFBD>潭綫<E6BDAD>𣂼<EFBFBD>?
| 隞餃𦛚蝐餃<E89D90> | <20><EFBFBD><E588BB><EFBFBD><EFBFBD>?| <20><>眏 |
- ❌ 小任务响应慢(队列有轮询间隔)
- ❌ 浪费队列资源
- ❌ 用户体验差
### 阈值推荐值
| 任务类型 | 推荐阈值 | 理由 |
|---------|---------|------|
| <EFBFBD><EFBFBD>讃蝑偦<EFBFBD>?| 50蝭?| <20><EFBFBD>~7蝘𡜐<E89D98>50蝭㻬5<E3BBAC><35><EFBFBD> |
| <EFBFBD>唳旿<EFBFBD>𣂼<EFBFBD> | 50<35>?| <20>閙辺~5-10蝘𡜐<E89D98>50<35>﹚5<EFB99A><35><EFBFBD> |
| 蝏蠘恣璅<EFBFBD> | 30銝?| <20>蓥葵~10蝘𡜐<E89D98>30銝泠5<E6B3A0><35><EFBFBD> |
| 暺䁅恕 | 50<EFBFBD>?| <20>𡁶鍂<F0A181B6><EFBFBD><E588BB>?|
| 文献筛选 | 50篇 | 单篇~7秒50篇~5分钟 |
| 数据提取 | 50条 | 单条~5-10秒50条~5分钟 |
| 统计模型 | 30个 | 单个~10秒30个~5分钟 |
| 默认 | 50条 | 通用推荐值 |
---
## <EFBFBD>?蝳<><EFBFBD>𡁏<EFBFBD>嚗㇄ON'T嚗?
### 1. <20>砍𧑐<E7A08D><F0A79190>辣摮睃<E691AE> <20>?
## ❌ 禁止做法DON'T
### 1. 本地文件存储 ❌
```typescript
// <EFBFBD>?蝳<>迫嚗𡁏𧋦<F0A1818F><EFBFBD>隞嗥頂蝏笔<E89D8F><E7AC94>?import fs from 'fs'
// ❌ 禁止:本地文件系统存储
import fs from 'fs'
export async function uploadFile(req, res) {
const file = await req.file()
const buffer = await file.toBuffer()
// <EFBFBD>?<3F>躰秤嚗𡁜捆<F0A1819C><EFBFBD><E588B8>臭腺憭? fs.writeFileSync('./uploads/file.pdf', buffer)
// ❌ 错误:容器重启丢失
fs.writeFileSync('./uploads/file.pdf', buffer)
res.send({ url: '/uploads/file.pdf' })
}
// <EFBFBD>?蝳<>迫嚗帋<E59A97>韏𡝗𧋦<F0A19D97>啗楝敺?const uploadDir = '/var/app/uploads'
// ❌ 禁止:依赖本地路径
const uploadDir = '/var/app/uploads'
const filePath = path.join(uploadDir, filename)
```
**<EFBFBD><EFBFBD>**嚗?- 摰孵膥<E5ADB5>滚鍳<E6BB9A>𡝗<EFBFBD>摰孵<E691B0><E5ADB5><EFBFBD>辣銝
**问题**
- 容器重启或扩容后文件丢失
- 多实例间无法共享文件
- 磁盘空间有限
**<EFBFBD><EFBFBD>𡁏<EFBFBD>**嚗帋蝙<E5B88B>?`storage.upload()` 銝𠹺<EFBFBD><EFBFBD>?OSS
**正确做法**:使用 `storage.upload()` 上传到 OSS
---
### 2. <EFBFBD><EFBFBD><EFBFBD>蝻枏<EFBFBD> <20>?
### 2. 内存缓存 ❌
```typescript
// <EFBFBD>?蝳<>迫嚗𡁜<E59A97>摮条<E691AE>摮矋<E691AE>憭𡁜<E686AD>靘衤<E99D98><E8A1A4>曹澈嚗?const cache = new Map<string, any>()
// ❌ 禁止:内存缓存(多实例不共享)
const cache = new Map<string, any>()
export async function getProject(id: string) {
// <EFBFBD>?<3F>躰秤嚗𡁏<E59A97>摰孵<E691B0><E5ADB5><EFBFBD>摰硺<E691B0>霂颱<E99C82><E9A2B1><EFBFBD>摮? if (cache.has(id)) {
// ❌ 错误:扩容后其他实例读不到缓存
if (cache.has(id)) {
return cache.get(id)
}
@@ -436,32 +512,42 @@ export async function getProject(id: string) {
return project
}
// <EFBFBD>?蝳<>迫嚗𡁜<E59A97><EFBFBD><E69285><EFBFBD>摮睃<E691AE><E79D83><EFBFBD>?let taskStatus = {} // 憭𡁜<E686AD>靘衤<E99D98><E8A1A4>峕郊
// ❌ 禁止:全局变量存储状态
let taskStatus = {} // 多实例不同步
```
**<EFBFBD><EFBFBD>**嚗?- 憭𡁜<E686AD>靘钅𡢿<E99285>唳旿銝滚<E98A9D>甇?- <20>拙捆<E68B99>𡒊<EFBFBD>摮睃仃<E79D83>?- <20><><EFBFBD><EFBFBD>删鍂銝滚虾<E6BB9A>?
**甇<><EFBFBD>𡁏<EFBFBD>**嚗帋蝙<E5B88B>?Redis <20>𡝗㺭<F0A19D97><EFBFBD>
**问题**
- 多实例间数据不同步
- 扩容后缓存失效
- 内存占用不可控
**正确做法**:使用 Redis 或数据库
---
### 3. 蝖祉<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝵?<3F>?
### 3. 硬编码配置 ❌
```typescript
// <EFBFBD>?蝳<>迫嚗𡁶蝻𣇉<E89DBB>
// ❌ 禁止:硬编码
const LLM_API_KEY = 'sk-xxx'
const DB_HOST = '192.168.1.100'
const OSS_BUCKET = 'my-bucket'
// <EFBFBD>?蝳<>迫嚗𡁜<E59A97>甇餌垢<E9A48C>?app.listen(3001)
// ❌ 禁止:写死端口
app.listen(3001)
// <EFBFBD>?蝳<>迫嚗𡁜<E59A97>甇餃<E79487><E9A483>?const baseUrl = 'https://api.example.com'
// ❌ 禁止:写死域名
const baseUrl = 'https://api.example.com'
```
**<EFBFBD><EFBFBD>**嚗?- <20><EFBFBD><E4ADBE><EFBFBD><EFBFBD><EFBFBD>
**问题**
- 无法切换环境
- 安全风险(密钥泄露)
- 部署困难
**<EFBFBD><EFBFBD>𡁏<EFBFBD>**嚗?```typescript
// <20>?雿輻鍂<E8BCBB><EFBFBD><E887AC><EFBFBD>
**正确做法**
```typescript
// ✅ 使用环境变量
const apiKey = process.env.LLM_API_KEY
const port = process.env.PORT || 3001
app.listen(port)
@@ -469,99 +555,124 @@ app.listen(port)
---
### 4. <EFBFBD>峕郊<EFBFBD>蹂遙<EFBFBD>?<3F>?
### 4. 同步长任务 ❌
```typescript
// <20>?蝳<>迫嚗𡁜<E59A97>甇亙<E79487><E4BA99><EFBFBD>鵭隞餃𦛚
// ❌ 禁止:同步处理长任务
export async function screenLiteratures(req, res) {
const literatures = await prisma.aslLiterature.findMany({...})
// <EFBFBD>?<3F>躰秤嚗?00蝭<30><EFBFBD><EFBFBD>餈?0蝘? for (const lit of literatures) {
await llmScreening(lit) // 瘥讐<E798A5>2-3蝘? }
// ❌ 错误100篇可能超过30秒
for (const lit of literatures) {
await llmScreening(lit) // 每篇2-3秒
}
res.send({ success: true }) // 可能已经超时
}
// <EFBFBD>?蝳<>迫嚗𡁏瓷<F0A1818F><EFBFBD><E39591><EFBFBD><E597A1>?const result = await axios.get(url) // <20><EFBFBD>瘞訾<E7989E>蝑匧<E89D91>
// ❌ 禁止:没有超时保护
const result = await axios.get(url) // 可能永久等待
```
**<EFBFBD><EFBFBD>**嚗?- SAE 霂瑟<E99C82><EFBFBD>𧒄 30 蝘?- <20>滨垢蝑匧<E89D91><E58CA7>園𡢿餈<F0A1A2BF>
**问题**
- SAE 请求超时 30 秒
- 前端等待时间过长
- 无法显示进度
**<EFBFBD><EFBFBD>𡁏<EFBFBD>**嚗𡁜<E59A97>甇乩遙<E4B9A9>?+ 餈𥕦漲頧株砭嚗<E7A0AD><E59A97> DO 蝚?<3F><EFBFBD>
**正确做法**:异步任务 + 进度轮询(见 DO 第4条
---
### 5. <EFBFBD>砍𧑐<EFBFBD><EFBFBD><EFBFBD><EFBFBD><20>?
### 5. 本地日志文件 ❌
```typescript
// <20>?蝳<>迫嚗𡁜<E59A97><F0A1819C>交𧋦<E4BAA4><EFBFBD>隞?import fs from 'fs'
// ❌ 禁止:写入本地文件
import fs from 'fs'
export function logError(error: Error) {
// <EFBFBD>?<3F>躰秤嚗𡁜捆<F0A1819C><EFBFBD><E588B8>臭腺憭梧<E686AD><E6A2A7><EFBFBD><E4ADBE><EFBFBD><EFBFBD><EFBFBD>
// ❌ 错误:容器重启丢失,无法集中查看
fs.appendFileSync('/var/log/app.log', error.message + '\n')
}
// <EFBFBD>?蝳<>迫嚗帋蝙<E5B88B>?console.log <EFBFBD><EFBFBD><EFBFBD>?logger
console.log('User logged in') // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗屸𠗕隞交䰻霂?```
// ❌ 禁止:使用 console.log 而不用 logger
console.log('User logged in') // 无结构化,难以查询
```
**<EFBFBD><EFBFBD>**嚗?- 摰孵膥<E5ADB5>滚鍳<E6BB9A><EFBFBD>
- 憭𡁜<E686AD>靘𧢲𠯫敹堒<E695B9><E5A092>?- <20><EFBFBD><E4ADBE><EFBFBD><EFBFBD><E89189><EFBFBD>
**问题**
- 容器重启日志丢失
- 多实例日志分散
- 无法集中分析
**<EFBFBD><EFBFBD>𡁏<EFBFBD>**嚗?```typescript
// <20>?颲枏枂<E69E8F>?stdout嚗䔶蝙<E494B6>?logger
**正确做法**
```typescript
// ✅ 输出到 stdout使用 logger
logger.info({ userId, action: 'login' }, 'User logged in')
```
---
### 6. <EFBFBD>啣遣<EFBFBD>唳旿摨栞<EFBFBD><EFBFBD>?<3F>?
### 6. 新建数据库连接 ❌
```typescript
// <20>?蝳<>迫嚗𡁏<E59A97>甈∟窈瘙<E7AA88>鰵撱箄<E692B1><E7AE84>?import { PrismaClient } from '@prisma/client'
// ❌ 禁止:每次请求新建连接
import { PrismaClient } from '@prisma/client'
export async function getProjects(req, res) {
// <EFBFBD>?<3F>躰秤嚗𡁏<E59A97>甈⊥鰵撱綽<E692B1>餈墧𦻖<E5A2A7>唳𠂔憓? const prisma = new PrismaClient()
// ❌ 错误:每次新建,连接数暴增
const prisma = new PrismaClient()
const projects = await prisma.aslScreeningProject.findMany()
await prisma.$disconnect()
res.send(projects)
}
// <EFBFBD>?蝳<>迫嚗𡁶凒<F0A181B6>乩蝙<E4B9A9>?pg <20><EFBFBD>隞㚚店<E39A9A>?import { Pool } from 'pg'
// ❌ 禁止:直接使用 pg 或其他驱动
import { Pool } from 'pg'
const pool = new Pool({ connectionString: process.env.DATABASE_URL })
```
**<EFBFBD><EFBFBD>**嚗?- 餈墧𦻖<E5A2A7>啣翰<E595A3><EFBFBD>堒偷嚗㇌DS<44>𣂼<EFBFBD> 400 餈墧𦻖嚗?- <20><EFBFBD>雿𦒘<E99BBF><EFBFBD><E59A97><EFBFBD>亙遣蝡贝<E89DA1>埈𧒄嚗?- 韏<><E99F8F>瘚芾晶
**问题**
- 连接数快速耗尽RDS限制 400 连接)
- 性能低下(连接建立耗时)
- 资源浪费
**<EFBFBD><EFBFBD>𡁏<EFBFBD>**嚗?```typescript
// <20>?雿輻鍂<E8BCBB><EFBFBD> Prisma Client
**正确做法**
```typescript
// ✅ 使用全局 Prisma Client
import { prisma } from '@/config/database'
const projects = await prisma.aslScreeningProject.findMany()
```
---
### 7. 敹賜裦<EFBFBD>躰秤 <20>?
### 7. 忽略错误 ❌
```typescript
// <20>?蝳<>迫嚗𡁶征<F0A181B6>?catch
// ❌ 禁止:空的 catch
try {
await storage.upload(key, buffer)
} catch (error) {
// <EFBFBD>?<3F>躰秤鋡怠<E98BA1><E680A0><EFBFBD><E39A81><EFBFBD><E4ADBE>埝䰻
// ❌ 错误被吞掉,无法排查
}
// <EFBFBD>?蝳<>迫嚗帋<E59A97><EFBFBD><E686AD> Promise rejection
// ❌ 禁止:不处理 Promise rejection
processAsync(taskId) // 没有 .catch()
// <EFBFBD>?蝳<>迫嚗朞<E59A97><E69C9E>墧芋蝟𢠃<E89D9F>霂?catch (error) {
// ❌ 禁止:返回模糊错误
catch (error) {
res.status(500).send({ error: 'Something went wrong' })
// 用户不知道什么错了,如何解决
}
```
**<EFBFBD><EFBFBD>**嚗?- <20>躰秤<E8BAB0><EFBFBD>餈質葵
- <20><EFBFBD>雿㯄<E99BBF>撌?- <20>埝䰻<E59F9D>圈𠗕
**问题**
- 错误无法追踪
- 用户体验差
- 排查困难
**<EFBFBD><EFBFBD>𡁏<EFBFBD>**嚗?```typescript
// <20>?霈啣<E99C88><E595A3><EFBFBD> + <20>见末<E8A781>躰秤靽⊥<E99DBD>
**正确做法**
```typescript
// ✅ 记录日志 + 友好错误信息
try {
await storage.upload(key, buffer)
} catch (error) {
@@ -578,39 +689,57 @@ try {
---
## <EFBFBD><EFBFBD><><E99A9E>摰⊥䰻璉<E4B0BB><E79289><EFBFBD><E4BAA4>?
<EFBFBD>?*<2A>𣂷漱隞<E6BCB1><E99A9E><EFBFBD>?*嚗諹窈<E8ABB9>鞾★璉<E29885><E79289><EFBFBD>
## 🔍 代码审查检查清单
在**提交代码前**,请逐项检查:
### 文件存储
- [ ] <20>臬炏雿輻鍂 `storage.upload()` <20><EFBFBD> `fs.writeFile()`嚗?- [ ] Excel <20>臬炏隞𤾸<E99A9E>摮䁅圾<E48185><EFBFBD><E7909C><EFBFBD>靽嘥<E99DBD><E598A5>唳𧋦<E594B3><EFBFBD>
- [ ] 是否使用 `storage.upload()` 而非 `fs.writeFile()`
- [ ] Excel 是否从内存解析,而非保存到本地?
- [ ] PDF 提取后是否立即删除临时文件?
### <EFBFBD>唳旿摨?- [ ] <20>臬炏雿輻鍂<E8BCBB><EFBFBD> `prisma` 摰硺<E691B0>嚗?- [ ] <20>臬炏<E887AC><EFBFBD><E8B8B9>典儐<E585B8>臭葉<E887AD><EFBFBD><E689AF>閙辺<E99699>亥砭嚗<E7A0AD><E59A97>摨磰砲<E7A3B0><EFBFBD><E5AFA5><EFBFBD>嚗?- [ ] <20><EFBFBD><E5AFA5><EFBFBD><E6BBA2>臬炏雿輻鍂鈭见𦛚嚗?
### 数据库
- [ ] 是否使用全局 `prisma` 实例?
- [ ] 是否避免在循环中执行单条查询?(应该批量操作)
- [ ] 批量操作是否使用事务?
### 配置管理
- [ ] <20>臬炏<E887AC><E7828F><EFBFBD><EFBFBD>蝵桅<E89DB5>隞?`process.env` 霂餃<E99C82>嚗?- [ ] <20>臬炏瘝⊥<E7989D>蝖祉<E89D96><E7A589><EFBFBD><EFBFBD> IP<49><50><EFBFBD><EFBFBD><EFBFBD><E6BABB><EFBFBD><EFBFBD><EFBFBD>
- [ ] 是否所有配置都从 `process.env` 读取?
- [ ] 是否没有硬编码的 IP、域名、密钥
- [ ] `.env.example` 是否已更新?
### <EFBFBD>踵𧒄<EFBFBD>港遙<EFBFBD>?- [ ] 頞<><E9A09E> 10 蝘垍<E89D98>隞餃𦛚<E9A483>臬炏<E887AC>嫣蛹撘<E89BB9>郊嚗?- [ ] <20>臬炏<E887AC>𣂷<EFBFBD><EFBFBD><E988AD>摨行䰻霂𦻖<EFBCB8><F0A6BB96><EFBFBD>
- [ ] <20>滨垢<E6BBA8>臬炏<E887AC>㕑蔭霂<E99C82> WebSocket <20><EFBFBD>餈𥕦漲嚗?
### 长时间任务
- [ ] 超过 10 秒的任务是否改为异步?
- [ ] 是否提供了进度查询接口?
- [ ] 前端是否有轮询或 WebSocket 获取进度?
### 日志
- [ ] <20>臬炏雿輻鍂 `logger` <20><EFBFBD> `console.log`嚗?- [ ] <20><EFBFBD><E4BA99>臬炏蝏𤘪<E89D8F><F0A498AA><EFBFBD>JSON<4F><EFBFBD>嚗㚁<E59A97>
- [ ] 是否使用 `logger` 而非 `console.log`
- [ ] 日志是否结构化JSON格式
- [ ] 是否记录了关键操作userId、action
### 错误处理
- [ ] <20><><EFBFBD>?async <20>賣㺭<E8B3A3>臬炏<E887AC>?try-catch嚗?- [ ] <20>臬炏霈啣<E99C88><EFBFBD>祕蝏<E7A595><E89D8F>霂舀𠯫敹梹<E695B9>
- [ ] <20>臬炏餈𥪜<E9A488><EFBFBD><E988AD>憟賜<E6869F><E8B39C>躰秤靽⊥<E99DBD>嚗?
- [ ] 所有 async 函数是否有 try-catch
- [ ] 是否记录了详细错误日志?
- [ ] 是否返回了友好的错误信息?
### 临时文件
- [ ] `/tmp` 目录使用后是否立即删除?
- [ ] <20>臬炏<E887AC>?`finally` <20>𦯀葉皜<E89189><E79A9C>嚗?- [ ] <20>臬炏<E887AC><EFBFBD><E8B8B9><EFBFBD>靘肽<E99D98> `/tmp`嚗?
- [ ] 是否在 `finally` 块中清理?
- [ ] 是否避免长期依赖 `/tmp`
---
## <EFBFBD>㴓 敹恍<E695B9>蠘䌊璉<E48C8A>嚗?<3F><><EFBFBD>嚗?
**餈鞱<E9A488>隞乩<E99A9E><E4B9A9>賭誘嚗峕<E59A97><E5B395>乩誨<E4B9A9><E8AAA8><EFBFBD>臬炏<E887AC><EFBFBD>閫?*嚗?
## 🎯 快速自检5分钟
**运行以下命令,检查代码中是否有违规**
```bash
# 检查是否有本地文件存储
grep -r "fs.writeFile\|fs.appendFile" backend/src/modules/
# <EFBFBD><EFBFBD>交糓<EFBFBD><EFBFBD>蝖祉<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝵?grep -r "sk-\|http://\|192.168" backend/src/modules/
# 检查是否有硬编码配置
grep -r "sk-\|http://\|192.168" backend/src/modules/
# 检查是否有新建 Prisma 连接
grep -r "new PrismaClient" backend/src/modules/
@@ -619,14 +748,15 @@ grep -r "new PrismaClient" backend/src/modules/
grep -r "console.log" backend/src/modules/
```
**<EFBFBD><EFBFBD>蝏𤘪<EFBFBD>**嚗𡁏<E59A97><F0A1818F><EFBFBD><E39787><EFBFBD>霂亥<E99C82><E4BAA5>?**0 銝芸龪<E88AB8>?*
**预期结果**:所有检查应该返回 **0 个匹配**
---
## <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>獢?
- [鈭穃<E988AD><E7A983><EFBFBD>蝵脫沲<E884AB><E6B2B2><EFBFBD><EFBFBD>㻩(../09-<2D><EFBFBD>摰墧鴌/03-鈭穃<E988AD><E7A983><EFBFBD>蝵脫沲<E884AB><E6B2B2><EFBFBD><EFBFBD>?md) - <20><>鉄摰峕㟲隞<E39FB2><E99A9E>蝷箔<E89DB7>
## 📚 参考文档
- [云原生部署架构指南](../09-架构实施/03-云原生部署架构指南.md) - 包含完整代码示例
- [前后端模块化架构设计-V2](../00-系统总体设计/前后端模块化架构设计-V2.md) - 架构总纲
- [<EFBFBD>唳旿摨栞挽霈∟<EFBFBD><EFBFBD><EFBFBD>(./01-<2D>唳旿摨栞挽霈∟<E99C88><E2889F>?md)
- [数据库设计规范](./01-数据库设计规范.md)
- [API设计规范](./02-API设计规范.md)
- [代码规范](./05-代码规范.md)
- [Git提交规范](./06-Git提交规范.md)
@@ -635,13 +765,14 @@ grep -r "console.log" backend/src/modules/
## 📝 更新日志
| <EFBFBD><EFBFBD> | <20><>𧋦 | <20>䀹凒<E480B9><E58792>捆 | 蝏湔擪<E6B994>?|
| 日期 | 版本 | 变更内容 | 维护者 |
|------|------|---------|--------|
| 2025-11-16 | V1.0 | <EFBFBD>𥕦遣<EFBFBD><EFBFBD>﹝嚗<EFBFBD><EFBFBD>銋劐<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>𤏸<EFBFBD><EFBFBD>?| <20><EFBFBD><E59786><EFBFBD> |
| 2025-11-16 | V1.0 | 创建文档,定义云原生开发规范 | 架构团队 |
---
**文档维护者:** 架构团队
**最后更新:** 2025-11-16
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>?撌脣<E6928C><E884A3>?
**撘箏<EFBFBD><EFBFBD><EFBFBD>嚗?* <20>?<3F><><EFBFBD>劐誨<E58A90><E8AAA8><EFBFBD>鈭文<E988AD><EFBFBD>◆璉<E29786><E79289>?
**文档状态:** ✅ 已完成
**强制执行:** ✅ 所有代码提交前必须检查

View File

@@ -1,4 +1,4 @@
# <EFBFBD>唳旿摨枏<EFBFBD><EFBFBD>𤏸<EFBFBD><EFBFBD>?
# 数据库开发规范
> 版本: v1.0
> 更新日期: 2026-01-11
@@ -14,27 +14,27 @@
⚠️ 黄金法则:任何数据库操作前,必须先备份!
```
### 1.2 <EFBFBD>迫雿輻鍂<EFBFBD><EFBFBD><EFBFBD>拙𦶢隞?
### 1.2 禁止使用的危险命令
| 命令 | 危险等级 | 说明 |
|------|----------|------|
| `prisma db push --force-reset` | <EFBFBD>𣞁 **<EFBFBD><EFBFBD><EFBFBD>** | 隡𡁜<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㗇㺭<EFBFBD><EFBFBD><EFBFBD>鱲risma蝞∠<EFBFBD><EFBFBD><EFBFBD>笆鞊?|
| `prisma migrate reset` | <EFBFBD>𣞁 **<EFBFBD><EFBFBD><EFBFBD>** | <EFBFBD>滨蔭<EFBFBD>港葵<EFBFBD>唳旿摨?|
| `DROP DATABASE` | <EFBFBD>𣞁 **<EFBFBD><EFBFBD><EFBFBD>** | <EFBFBD>𣳇膄<EFBFBD>港葵<EFBFBD>唳旿摨?|
| `TRUNCATE TABLE` | <EFBFBD><EFBFBD> 擃?| 皜<>征銵冽㺭<E586BD>?|
| `prisma db push --force-reset` | 🔴 **极高** | 会删除所有数据和非Prisma管理的对象 |
| `prisma migrate reset` | 🔴 **极高** | 重置整个数据库 |
| `DROP DATABASE` | 🔴 **极高** | 删除整个数据库 |
| `TRUNCATE TABLE` | 🟠 高 | 清空表数据 |
### 1.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>典𦶢隞?
### 1.3 推荐的安全命令
| <EFBFBD>賭誘 | <20><EFBFBD>?| 摰匧<E691B0><E58CA7>?|
| 命令 | 用途 | 安全性 |
|------|------|--------|
| `prisma migrate dev` | <EFBFBD><EFBFBD>𤑳㴓憓<EFBFBD><EFBFBD>蝘?| <20>?摰匧<E691B0> |
| `prisma migrate deploy` | <EFBFBD>煺漣<EFBFBD><EFBFBD><EFBFBD>宏 | <20>?摰匧<E691B0> |
| `prisma db push` (<EFBFBD>?--force-reset) | <EFBFBD>峕郊schema<EFBFBD>唳㺭<EFBFBD><EFBFBD> | <20>𩤃<EFBFBD> 靚冽<E99D9A>雿輻鍂 |
| `prisma generate` | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝡?| <20>?摰匧<E691B0> |
| `prisma migrate dev` | 开发环境迁移 | ✅ 安全 |
| `prisma migrate deploy` | 生产环境迁移 | ✅ 安全 |
| `prisma db push` (--force-reset) | 同步schema到数据库 | ⚠️ 谨慎使用 |
| `prisma generate` | 生成客户端 | ✅ 安全 |
---
## 2. <EFBFBD>唳旿摨枏<EFBFBD>隞質<EFBFBD><EFBFBD>?
## 2. 数据库备份规范
### 2.1 备份命令
@@ -51,11 +51,11 @@ docker exec ai-clinical-postgres pg_dump -U postgres -d ai_clinical_research > "
| 时机 | 是否必须 |
|------|----------|
| <EFBFBD><EFBFBD>隞颱<EFBFBD> `prisma migrate` <EFBFBD>?| <20>?敹<> |
| <EFBFBD><EFBFBD> `prisma db push` <EFBFBD>?| <20>?敹<> |
| <EFBFBD>函蔡<EFBFBD><EFBFBD>鈭抒㴓憓<EFBFBD><EFBFBD> | <20>?敹<> |
| 瘥𤩺𠯫<EFBFBD>芸𢆡憭<EFBFBD>遢 | <20>?<3F><EFBFBD> |
| <EFBFBD>滚之<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?| <20>?敹<> |
| 执行任何 `prisma migrate` 前 | ✅ 必须 |
| 执行 `prisma db push` 前 | ✅ 必须 |
| 部署到生产环境前 | ✅ 必须 |
| 每日自动备份 | ✅ 推荐 |
| 重大功能发布前 | ✅ 必须 |
### 2.3 备份文件管理
@@ -87,7 +87,7 @@ graph TD
### 3.2 具体步骤
```bash
# 1. <EFBFBD><EFBFBD>唳旿摨?
# 1. 备份数据库
docker exec ai-clinical-postgres pg_dump -U postgres -d ai_clinical_research > backup_before_migration.sql
# 2. 修改 schema.prisma
@@ -100,36 +100,36 @@ cat prisma/migrations/xxx_describe_your_change/migration.sql
# 5. 测试
# 6. <EFBFBD><EFBFBD>憭梯揖嚗峕<EFBFBD>憭滚<EFBFBD>隞?
# 6. 如果失败,恢复备份
cat backup_before_migration.sql | docker exec -i ai-clinical-postgres psql -U postgres -d ai_clinical_research
```
---
## 4. Prisma 銝擧㺭<EFBFBD><EFBFBD>銝滢<EFBFBD><EFBFBD>湧䔮憸?
## 4. Prisma 与数据库不一致问题
### 4.1 Prisma 不管理的对象
隞乩<EFBFBD><EFBFBD>唳旿摨枏笆鞊∩<EFBFBD><EFBFBD>?`schema.prisma` 銝剖<EFBFBD>銋㚁<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>祉恣<EFBFBD><EFBFBD><EFBFBD>
以下数据库对象不在 `schema.prisma` 中定义,需要单独管理:
| 对象 | 类型 | 来源 | 恢复脚本 |
|------|------|------|----------|
| `platform_schema.job_common` | 銵?| pg-boss 餈鞱<EFBFBD><EFBFBD><EFBFBD>撱?| `restore_job_common.sql` |
| `platform_schema.create_queue()` | <EFBFBD>賣㺭 | pg-boss <EFBFBD><EFBFBD><EFBFBD>?| `restore_pgboss_functions.sql` |
| `platform_schema.delete_queue()` | <EFBFBD>賣㺭 | pg-boss <EFBFBD><EFBFBD><EFBFBD>?| `restore_pgboss_functions.sql` |
| `platform_schema.job_common` | | pg-boss 运行时创建 | `restore_job_common.sql` |
| `platform_schema.create_queue()` | 函数 | pg-boss 初始化 | `restore_pgboss_functions.sql` |
| `platform_schema.delete_queue()` | 函数 | pg-boss 初始化 | `restore_pgboss_functions.sql` |
### 4.2 <EFBFBD><EFBFBD><EFBFBD>?Prisma 蝞∠<EFBFBD><EFBFBD><EFBFBD>笆鞊?
### 4.2 恢复非 Prisma 管理的对象
```bash
# <EFBFBD><EFBFBD>霂臬<EFBFBD>鈭?pg-boss <20><EFBFBD>撖寡情嚗峕<E59A97>銵䕘<E98AB5>
# 如果误删了 pg-boss 相关对象,执行:
npx prisma db execute --file restore_job_common.sql --schema prisma/schema.prisma
npx prisma db execute --file restore_pgboss_functions.sql --schema prisma/schema.prisma
```
### 4.3 <EFBFBD><EFBFBD>交㺭<EFBFBD><EFBFBD>銝?Prisma <EFBFBD><EFBFBD><EFBFBD>?
### 4.3 检查数据库与 Prisma 一致性
```bash
# <EFBFBD><EFBFBD><EFBFBD>唳旿摨㮖葉<EFBFBD><EFBFBD><EFBFBD>?
# 查看数据库中的函数
SELECT routine_name FROM information_schema.routines WHERE routine_schema = 'platform_schema';
# 查看数据库中的表
@@ -140,29 +140,29 @@ SELECT table_name FROM information_schema.tables WHERE table_schema = 'platform_
---
## 5. 憭?Schema <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
## 5. Schema 架构规范
### 5.1 Schema 命名规范
| Schema | <EFBFBD><EFBFBD>?| 蝷箔<E89DB7>銵?|
| Schema | 用途 | 示例表 |
|--------|------|--------|
| `platform_schema` | 平台基础设施 | users, tenants, app_cache |
| `admin_schema` | 运营管理 | admin_operation_logs |
| `aia_schema` | AI智能问答 | conversations, messages |
| `asl_schema` | <EFBFBD><EFBFBD>讃蝑偦<EFBFBD>?| screening_projects, literatures |
| `asl_schema` | 文献筛选 | screening_projects, literatures |
| `dc_schema` | 数据清洗 | dc_templates, dc_extraction_tasks |
| `pkb_schema` | 銝芯犖<EFBFBD><EFBFBD>摨?| knowledge_bases, documents |
| `pkb_schema` | 个人知识库 | knowledge_bases, documents |
| `iit_schema` | IIT项目 | projects, audit_logs |
| `rvw_schema` | 论文预审 | review_tasks |
| `capability_schema` | 通用能力 | prompt_templates |
| `public` | <EFBFBD>扳㺭<EFBFBD>?<3F>澆捆 | users (<EFBFBD>?, admin_logs |
| `public` | 旧数据/兼容 | users (旧), admin_logs |
### 5.2 銵典𦶢<EFBFBD><EFBFBD><EFBFBD>?
### 5.2 表命名规范
```
{schema_name}.{module_prefix}_{entity_name}
蝷箔<EFBFBD>嚗?
示例:
- dc_schema.dc_templates
- dc_schema.dc_extraction_tasks
- asl_schema.screening_projects
@@ -170,12 +170,12 @@ SELECT table_name FROM information_schema.tables WHERE table_schema = 'platform_
---
## 6. 憭㚚睸銝擧㺭<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
## 6. 外键与数据完整性
### 6.1 頝?Schema 憭㚚睸
### 6.1 Schema 外键
```prisma
// <EFBFBD>?甇<>嚗𡁏<E59A97>蝖格<E89D96>摰𡁜<E691B0>蝟?
// ✅ 正确:明确指定关系
model ReviewTask {
userId String @map("user_id")
user PublicUser @relation(fields: [userId], references: [id])
@@ -191,9 +191,9 @@ model PublicUser {
}
```
### 6.2 憭㚚睸<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
### 6.2 外键指向检查
<EFBFBD>其蝙<EFBFBD>?`prisma db push` <EFBFBD>𠬍<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>格糓<EFBFBD>行迤蝖殷<EFBFBD>
在使用 `prisma db push` 后,检查外键是否正确:
```sql
SELECT
@@ -213,7 +213,7 @@ WHERE tc.constraint_type = 'FOREIGN KEY';
```bash
# 1. 停止应用
# 2. 隞𤾸<EFBFBD>隞賣<EFBFBD>憭?
# 2. 从备份恢复
cat backup_xxx.sql | docker exec -i ai-clinical-postgres psql -U postgres -d ai_clinical_research
# 3. 验证数据
@@ -222,13 +222,13 @@ npx tsx verify_system.ts
# 4. 重启应用
```
### 7.2 Schema 銝滢<EFBFBD><EFBFBD><EFBFBD>憭?
### 7.2 Schema 不一致恢复
```bash
# 1. <EFBFBD><EFBFBD>亙榆撘?
# 1. 检查差异
npx tsx compare_schema_db.ts
# 2. <EFBFBD><EFBFBD>蝻箏仃<EFBFBD><EFBFBD>笆鞊?
# 2. 恢复缺失的对象
npx prisma db execute --file restore_xxx.sql --schema prisma/schema.prisma
# 3. 验证
@@ -236,37 +236,37 @@ npx prisma db execute --file restore_xxx.sql --schema prisma/schema.prisma
---
## 8. <EFBFBD><EFBFBD>𤑳㴓憓?vs <20>煺漣<E785BA><EFBFBD>
## 8. 开发环境 vs 生产环境
### 8.1 <EFBFBD><EFBFBD>𤑳㴓憓?
### 8.1 开发环境
- 可以使用 `prisma migrate dev`
- 可以使用 `prisma db push`(谨慎)
- 摰𡁏<EFBFBD><EFBFBD>峕郊<EFBFBD>煺漣<EFBFBD>唳旿摨梶<EFBFBD><EFBFBD>?
- 定期同步生产数据库结构
### 8.2 生产环境
- **只能**使用 `prisma migrate deploy`
- **<EFBFBD>迫**雿輻鍂隞颱<E99A9E> `--force` <EFBFBD>?`--reset` <EFBFBD><EFBFBD>
- **禁止**使用任何 `--force` `--reset` 参数
- 变更前必须有回滚计划
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞?
- 必须有最新备份
---
## 9. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
## 9. 检查清单
### 9.1 <EFBFBD>唳旿摨枏<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
### 9.1 数据库变更前检查
- [ ] 已备份数据库
- [ ] 撌脣恣<EFBFBD>?schema.prisma <EFBFBD>䀹凒
- [ ] 撌脫<EFBFBD><EFBFBD>交糓<EFBFBD>血蔣<EFBFBD><EFBFBD> Prisma 蝞∠<E89D9E><E288A0><EFBFBD>笆鞊?
- [ ] 撌脣<EFBFBD><EFBFBD><EFBFBD>皛𡁏䲮獢?
- [ ] 撌脣銁撘<EFBFBD><EFBFBD>𤑳㴓憓<EFBFBD><EFBFBD>霂?
- [ ] 已审查 schema.prisma 变更
- [ ] 已检查是否影响非 Prisma 管理的对象
- [ ] 已准备回滚方案
- [ ] 已在开发环境测试
### 9.2 <EFBFBD>函蔡<EFBFBD><EFBFBD><EFBFBD>?
### 9.2 部署后检查
- [ ] 应用正常启动
- [ ] <EFBFBD>唳旿摨栞<EFBFBD><EFBFBD>交迤撣?
- [ ] 数据库连接正常
- [ ] pg-boss 队列正常工作
- [ ] 核心功能测试通过
@@ -278,14 +278,14 @@ npx prisma db execute --file restore_xxx.sql --schema prisma/schema.prisma
```
backend/
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> verify_system.ts # 蝟餌<EFBFBD>摰峕㟲<EFBFBD><EFBFBD>霂?
├── verify_system.ts # 系统完整性验证
├── compare_schema_db.ts # Schema与数据库对比
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> check_iit_asl_data.ts # <EFBFBD><EFBFBD>交芋<EFBFBD>埈㺭<EFBFBD>?
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> restore_job_common.sql # <EFBFBD><EFBFBD> job_common 銵?
├── check_iit_asl_data.ts # 检查模块数据
├── restore_job_common.sql # 恢复 job_common
└── restore_pgboss_functions.sql # 恢复 pg-boss 函数
```
### 10.2 敹恍<EFBFBD><EFBFBD><EFBFBD>𦶢隞?
### 10.2 快速验证命令
```bash
# 设置环境变量
@@ -294,27 +294,27 @@ $env:DATABASE_URL="postgresql://postgres:postgres123@localhost:5432/ai_clinical_
# 验证系统
npx tsx verify_system.ts
# <EFBFBD><EFBFBD>交㺭<EFBFBD>?
# 检查数据
npx tsx check_iit_asl_data.ts
```
---
## <EFBFBD><EFBFBD><EFBFBD>嚗帋<EFBFBD><EFBFBD><EFBFBD><EFBFBD>靘?
## 附录:事故案例
### <EFBFBD><EFBFBD>1嚗?026-01-11 <EFBFBD>唳旿摨㯄<EFBFBD>蝵桐<EFBFBD><EFBFBD>?
### 案例12026-01-11 数据库重置事故
**<EFBFBD><EFBFBD>**嚗帋蝙<E5B88B>?`prisma db push --force-reset` 撖潸稲<EFBFBD>?Prisma 蝞∠<EFBFBD><EFBFBD><EFBFBD>笆鞊∩腺憭?
**原因**:使用 `prisma db push --force-reset` 导致非 Prisma 管理的对象丢失
**敶勗<EFBFBD>**嚗?
- pg-boss <EFBFBD>賣㺭銝仃嚗屸<EFBFBD><EFBFBD><EFBFBD>瘜閙釣<EFBFBD>?
- job_common 銵其腺憭?
- <EFBFBD><EFBFBD><EFBFBD>唳旿銝仃嚗<EFBFBD><EFBFBD><EFBFBD> seed <EFBFBD><EFBFBD>嚗?
**影响**
- pg-boss 函数丢失,队列无法注册
- job_common 表丢失
- 用户数据丢失(已通过 seed 恢复)
**<EFBFBD>躰悌**嚗?
**教训**
1. 永远不要使用 `--force-reset`
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>憿餃<EFBFBD>隞?
3. <EFBFBD> Prisma <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
2. 操作前必须备份
3. 了解 Prisma 的管理边界
详见:`docs/08-项目管理/2026-01-11-数据库事故总结.md`
@@ -323,4 +323,3 @@ npx tsx check_iit_asl_data.ts

View File

@@ -1,29 +1,29 @@
# 模块认证规范
> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>銋劐<EFBFBD>銝𡁜𦛚璅<EFBFBD><EFBFBD><EFBFBD><EFBFBD>雿輻鍂撟喳蝱霈方<EFBFBD><EFBFBD><EFBFBD>嚗𣬚靽脲<EFBFBD><EFBFBD>?API <20>賣迤蝖格𡉼撣血<E692A3>撉諹<E69289><E8ABB9><EFBFBD>頨思遢<E6809D>?
> 本文档定义了业务模块如何正确使用平台认证能力,确保所有 API 都正确携带和验证用户身份。
## 1. 架构概览
```
<EFBFBD>𢞖<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<EFBFBD>? <EFBFBD>滨垢 <EFBFBD>?
<EFBFBD>? <20>𢞖<EFBFBD><F0A29E96><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<EFBFBD>? <20>? common/api/axios.ts <EFBFBD>?撣西恕霂<E68195><E99C82> axios 摰硺<EFBFBD> <EFBFBD>? <20>?
<EFBFBD>? <20>? framework/auth/api.ts <EFBFBD>?Token 蝞∠<EFBFBD> (getAccessToken)<EFBFBD>? <20>?
<EFBFBD>? <20><EFBFBD><E5A999><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<EFBFBD>?
<EFBFBD>?Authorization: Bearer <token>
<EFBFBD>?
<EFBFBD>𢞖<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<EFBFBD>? <EFBFBD>𡒊垢 <EFBFBD>?
<EFBFBD>? <20>𢞖<EFBFBD><F0A29E96><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<EFBFBD>? <20>? common/auth/auth.middleware.ts <EFBFBD>? <20>?
<EFBFBD>? <20>? - authenticate: 撉諹<EFBFBD> JWT Token <EFBFBD>? <20>?
<EFBFBD>? <20>? - requirePermission: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <EFBFBD>? <20>?
<EFBFBD>? <20>? - requireRoles: 閫坿𠧧璉<EFBFBD><EFBFBD>? <EFBFBD>? <20>?
<EFBFBD>? <20><EFBFBD><E5A999><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
┌─────────────────────────────────────────────────────────────┐
前端
│ ┌─────────────────────────────────────────────────────┐ │
│ │ common/api/axios.ts ← 带认证的 axios 实例 │ │
│ │ framework/auth/api.ts Token 管理 (getAccessToken)│ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Authorization: Bearer <token>
┌─────────────────────────────────────────────────────────────┐
后端
│ ┌─────────────────────────────────────────────────────┐ │
│ │ common/auth/auth.middleware.ts │ │
│ │ - authenticate: 验证 JWT Token │ │
│ │ - requirePermission: 权限检查 │ │
│ │ - requireRoles: 角色检查 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
## 2. 前端规范
@@ -34,12 +34,12 @@
// 导入带认证的 apiClient
import apiClient from '../../../common/api/axios';
// 雿輻鍂<EFBFBD><EFBFBD>銝?axios 摰<><E691B0><EFBFBD><EFBFBD>嚗諹䌊<E8ABB9>冽𡉼撣?JWT Token
// 使用方式与 axios 完全相同,自动携带 JWT Token
const response = await apiClient.get('/api/v2/xxx');
const response = await apiClient.post('/api/v2/xxx', data);
```
### 2.2 雿輻鍂<EFBFBD><EFBFBD> fetch嚗<68><E59A97><EFBFBD>见𢆡瘛餃<E7989B> Token嚗?
### 2.2 使用原生 fetch需手动添加 Token
```typescript
import { getAccessToken } from '../../../framework/auth/api';
@@ -56,12 +56,12 @@ function getAuthHeaders(): HeadersInit {
return headers;
}
// <EFBFBD><EFBFBD><EFBFBD>?fetch 霂瑟<EFBFBD>雿輻鍂 getAuthHeaders()
// 所有 fetch 请求使用 getAuthHeaders()
const response = await fetch(url, {
headers: getAuthHeaders(),
});
// <EFBFBD><EFBFBD>辣銝𠹺<EFBFBD><EFBFBD><EFBFBD>霈曄蔭 Content-Type嚗?
// 文件上传(不设置 Content-Type
const token = getAccessToken();
const headers: HeadersInit = {};
if (token) {
@@ -76,22 +76,22 @@ const response = await fetch(url, {
## 3. 后端规范
### 3.1 頝舐眏瘛餃<EFBFBD>霈方<EFBFBD>銝剝𡢿隞?
### 3.1 路由添加认证中间件
```typescript
// 撖澆<EFBFBD>霈方<EFBFBD>銝剝𡢿隞?
// 导入认证中间件
import { authenticate, requirePermission } from '../../../common/auth/auth.middleware.js';
// 瘛餃<EFBFBD><EFBFBD>啗楝<EFBFBD>?
// 添加到路由
fastify.get('/xxx', { preHandler: [authenticate] }, handler);
// <EFBFBD><EFBFBD><EFBFBD>鸌摰𡁏<EFBFBD><EFBFBD>?
// 需要特定权限
fastify.post('/xxx', {
preHandler: [authenticate, requirePermission('module:action')]
}, handler);
```
### 3.2 <EFBFBD><EFBFBD><EFBFBD>刻繮<EFBFBD>𣇉鍂<EFBFBD>?ID
### 3.2 控制器获取用户 ID
```typescript
/**
@@ -105,7 +105,7 @@ function getUserId(request: FastifyRequest): string {
return userId;
}
// <EFBFBD>冽綉<EFBFBD>嗅膥<EFBFBD><EFBFBD>銝凋蝙<EFBFBD>?
// 在控制器方法中使用
async function myHandler(request: FastifyRequest, reply: FastifyReply) {
const userId = getUserId(request);
// ... 使用 userId
@@ -117,7 +117,7 @@ async function myHandler(request: FastifyRequest, reply: FastifyReply) {
```typescript
interface DecodedToken {
userId: string; // 用户ID
phone: string; // <EFBFBD>𧢲㦤<EFBFBD>?
phone: string; // 手机号
role: string; // 角色
tenantId: string; // 租户ID
tenantCode?: string; // 租户Code
@@ -126,69 +126,68 @@ interface DecodedToken {
}
```
## 4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
## 4. 检查清单
### 4.1 <EFBFBD>唳芋<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
### 4.1 新模块开发检查清单
- [ ] **前端 API 文件**
- [ ] 雿輻鍂 `apiClient` <EFBFBD>𡝗溶<EFBFBD>?`getAuthHeaders()`
- [ ] <EFBFBD><EFBFBD>辣銝𠹺<EFBFBD><EFBFBD>閧𡠺憭<EFBFBD><EFBFBD><EFBFBD><EFBFBD>霈曄蔭 Content-Type嚗?
- [ ] 使用 `apiClient` 或添加 `getAuthHeaders()`
- [ ] 文件上传单独处理(不设置 Content-Type
- [ ] 导出函数不包含测试用 userId 参数
- [ ] **后端路由文件**
- [ ] 撖澆<EFBFBD> `authenticate` 銝剝𡢿隞?
- [ ] 导入 `authenticate` 中间件
- [ ] 所有需要认证的路由添加 `preHandler: [authenticate]`
- [ ] <EFBFBD><EFBFBD> API<EFBFBD><EFBFBD>璅⊥踎<EFBFBD>𡑒”嚗匧虾銝齿溶<EFBFBD>㰘恕霂?
- [ ] 公开 API(如模板列表)可不添加认证
- [ ] **<EFBFBD>𡒊垢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞?*
- [ ] **后端控制器文件**
- [ ] 添加 `getUserId()` 辅助函数
- [ ] 蝘駁膄<EFBFBD><EFBFBD><EFBFBD>?`MOCK_USER_ID` <EFBFBD>𣇉蝻𣇉<EFBFBD>暺䁅恕<EFBFBD>?
- [ ] 移除所有 `MOCK_USER_ID` 或硬编码默认值
- [ ] 使用 `getUserId(request)` 获取用户 ID
### 4.2 撌脣<EFBFBD><EFBFBD>鞉芋<EFBFBD>㛖𠶖<EFBFBD>?
### 4.2 已完成模块状态
| <EFBFBD> | <20>滨垢 API | <20>𡒊垢頝舐眏 | <20>𡒊垢<F0A1928A><EFBFBD><E689B9>?| <20><EFBFBD>?|
| 模块 | 前端 API | 后端路由 | 后端控制器 | 状态 |
|------|---------|---------|-----------|------|
| RVW | <EFBFBD>?apiClient | <EFBFBD>?authenticate | <EFBFBD>?getUserId | <EFBFBD>?|
| PKB | <EFBFBD>?<3F>行⏛<E8A18C>?| <20>?authenticate | <EFBFBD>?getUserId | <EFBFBD>?|
| ASL | <EFBFBD>?getAuthHeaders | <EFBFBD>?authenticate | <EFBFBD>?getUserId | <EFBFBD>?|
| DC Tool B | <EFBFBD>?getAuthHeaders | <EFBFBD>?authenticate | <EFBFBD>?getUserId | <EFBFBD>?|
| DC Tool C | <EFBFBD>?apiClient | <EFBFBD>?authenticate | <EFBFBD>?getUserId | <EFBFBD>?|
| IIT | N/A (<EFBFBD><EFBFBD>敺桐縑) | N/A | <EFBFBD>?隡<><E99AA1>敺桐縑userId | <EFBFBD>?|
| Prompt蝞∠<EFBFBD> | <EFBFBD>?getAuthHeaders | <EFBFBD>?authenticate | <EFBFBD>?getUserId | <EFBFBD>?|
| RVW | apiClient | authenticate | getUserId | |
| PKB | ✅ 拦截器 | ✅ authenticate | getUserId | |
| ASL | getAuthHeaders | authenticate | getUserId | |
| DC Tool B | getAuthHeaders | authenticate | getUserId | |
| DC Tool C | apiClient | authenticate | getUserId | |
| IIT | N/A (企业微信) | N/A | ✅ 企业微信userId | |
| Prompt管理 | getAuthHeaders | authenticate | getUserId | |
## 5. 撣貉<EFBFBD><EFBFBD>躰秤<EFBFBD>諹圾<EFBFBD>單䲮獢?
## 5. 常见错误和解决方案
### 5.1 401 Unauthorized
**<EFBFBD><EFBFBD>**: <EFBFBD>滨垢瘝⊥<EFBFBD><EFBFBD>箏蒂 JWT Token <EFBFBD>?Token <EFBFBD><EFBFBD>
**原因**: 前端没有携带 JWT Token Token 过期
**解决**:
1. <EFBFBD><EFBFBD><EFBFBD>蝡?API <20>臬炏雿輻鍂 `apiClient` <EFBFBD>?`getAuthHeaders()`
2. <EFBFBD><EFBFBD>?localStorage 銝剜糓<EFBFBD><EFBFBD> `accessToken`
1. 检查前端 API 是否使用 `apiClient` `getAuthHeaders()`
2. 检查 localStorage 中是否有 `accessToken`
3. 如果 Token 过期,尝试刷新或重新登录
### 5.2 User not authenticated
**<EFBFBD><EFBFBD>**: <EFBFBD>𡒊垢頝舐眏瘝⊥<EFBFBD>瘛餃<EFBFBD> `authenticate` 銝剝𡢿隞?
**原因**: 后端路由没有添加 `authenticate` 中间件
**解决**: 在路由定义中添加 `preHandler: [authenticate]`
### 5.3 TypeError: Cannot read property 'userId' of undefined
**<EFBFBD><EFBFBD>**: 雿輻鍂鈭<EFBFBD><EFBFBD>霂舐<EFBFBD>撅墧<EFBFBD><EFBFBD>嚗Ǒrequest.user.id` <20><EFBFBD> `request.user.userId`嚗?
**原因**: 使用了错误的属性名(`request.user.id` 而非 `request.user.userId`
**解决**: 使用 `(request as any).user?.userId`
## 6. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞?
## 6. 参考文件
- 前端 axios 实例: `frontend-v2/src/common/api/axios.ts`
- 前端 Token 管理: `frontend-v2/src/framework/auth/api.ts`
- <20>𡒊垢霈方<E99C88>銝剝𡢿隞? `backend/src/common/auth/auth.middleware.ts`
- 后端认证中间件: `backend/src/common/auth/auth.middleware.ts`
- 后端 JWT 服务: `backend/src/common/auth/jwt.service.ts`

View File

@@ -1,14 +1,17 @@
# 04-寮€鍙戣<EFBFBD>鑼?
> **鐩<>爣锛?* 缁熶竴鍥㈤槦寮€鍙戣<E98D99>鑼冿紝鎻愰珮浠爜璐ㄩ噺鍜屽崗浣滄晥鐜?
> **閫傜敤鑼冨洿锛?* 骞冲彴灞?+ 鑳藉姏灞?+ 涓氬姟妯″潡灞?
> **寮哄埗绛夌骇锛?* 猸愨瓙猸愨瓙猸?蹇呴』閬靛畧
# 04-开发规范
> **目标:** 统一团队开发规范,提高代码质量和协作效率
> **适用范围:** 平台层 + 能力层 + 业务模块层
> **强制等级:** ⭐⭐⭐⭐⭐ 必须遵守
---
## 📋 规范文档列表
### 1. 鏁版嵁搴撹<EFBFBD>璁¤<EFBFBD>鑼?猸愨瓙猸愨瓙猸?**鏂囦欢锛?* `01-鏁版嵁搴撹<E690B4>璁¤<E79281>鑼?md` 鈴?寰呭垱寤猴紙浠?`01-璁捐<E79281>鏂囨。/鏁版嵁搴撹<E690B4>璁℃枃妗?md` 鎻愬彇锛?
**鏍稿績鍐呭<EFBFBD>锛?*
### 1. 数据库设计规范 ⭐⭐⭐⭐⭐
**文件:** `01-数据库设计规范.md` ⏳ 待创建(从 `01-设计文档/数据库设计文档.md` 提取)
**核心内容:**
- Schema隔离策略platform_schema、asl_schema等
- 表命名规范(小写+下划线)
- 字段命名规范
@@ -16,41 +19,55 @@
- 外键约束规范
- 通用字段created_at、updated_at等
**<EFBFBD>€熷弬鑰冿細** [鏁版嵁搴撳叏灞€瑙嗗浘](./03-鏁版嵁搴撳叏灞€瑙嗗浘.md) 猸?宸插垱寤?
**快速参考:** [数据库全局视图](./03-数据库全局视图.md) ⭐ 已创建
---
### 2. API璁捐<EFBFBD>瑙勮寖 猸愨瓙猸愨瓙猸?**鏂囦欢锛?* `02-API璁捐<E79281>瑙勮寖.md` 鈴?寰呭垱寤猴紙浠?`01-璁捐<E79281>鏂囨。/API璁捐<E79281>瑙勮寖.md` 鎻愬彇锛?
**鏍稿績鍐呭<EFBFBD>锛?*
### 2. API设计规范 ⭐⭐⭐⭐⭐
**文件:** `02-API设计规范.md` ⏳ 待创建(从 `01-设计文档/API设计规范.md` 提取)
**核心内容:**
- RESTful API设计原则
- URL鍛藉悕瑙勮寖锛坄/api/v1/妯″潡/璧勬簮`锛?- HTTP鏂规硶浣跨敤瑙勮寖
- URL命名规范(`/api/v1/模块/资源`
- HTTP方法使用规范
- 请求/响应格式规范
- 閿欒<EFBFBD>鐮佽<EFBFBD>璁?- 璁よ瘉鍜屾潈闄?
**蹇<>€熷弬鑰冿細** [API璺<EFBFBD>敱鎬昏<EFBFBD>](./04-API璺<49>敱鎬昏<E98EAC>.md) 猸?宸插垱寤?
- 错误码设计
- 认证和权限
**快速参考:** [API路由总览](./04-API路由总览.md) ⭐ 已创建
---
### 3. 鏁版嵁搴撳叏灞€瑙嗗浘 猸愨瓙猸愨瓙猸?鉁?鏂板<E98F82>
**鏂囦欢锛?* `03-鏁版嵁搴撳叏灞€瑙嗗浘.md`
### 3. 数据库全局视图 ⭐⭐⭐⭐⭐ ✅ 新增
**文件:** `03-数据库全局视图.md`
**鐢ㄩ€旓細** 鎻愪緵鎵€鏈塖chema鍜岃〃鐨勫揩閫熺储寮?
**鏍稿績鍐呭<E98D90>锛?*
- Schema鍒掑垎绛栫暐锛?涓猄chema锛?- 鎵€鏈夎〃鐨勬€昏<E282AC>鍜岃烦杞<E783A6>摼鎺?- 璺⊿chema渚濊禆鍏崇郴
- 鏁版嵁閲忛<EFBFBD>浼?
**浣跨敤鍦烘櫙锛?*
**用途:** 提供所有Schema和表的快速索引
**核心内容:**
- Schema划分策略8个Schema
- 所有表的总览和跳转链接
- 跨Schema依赖关系
- 数据量预估
**使用场景:**
- 查看全局数据架构
- 快速定位某个表属于哪个Schema
- 浜嗚В璺ㄦā鍧楁暟鎹<EFBFBD>叧绯?
- 了解跨模块数据关系
---
### 4. API<EFBFBD>敱鎬昏<EFBFBD> 猸愨瓙猸愨瓙猸?鉁?鏂板<E98F82>
**鏂囦欢锛?* `04-API<EFBFBD>敱鎬昏<EFBFBD>.md`
### 4. API路由总览 ⭐⭐⭐⭐⭐ ✅ 新增
**文件:** `04-API路由总览.md`
**鐢ㄩ€旓細** 鎻愪緵鎵€鏈堿PI绔<EFBFBD>偣鐨勫揩閫熺储寮?
**鏍稿績鍐呭<E98D90>锛?*
**用途:** 提供所有API端点的快速索引
**核心内容:**
- 路由命名规范
- 所有模块的API端点总览
- <EFBFBD>敱鍐茬獊妫€鏌?- 绔<>偣缁熻<E7BC81>锛垀85涓<35>
- 路由冲突检查
- 端点统计(~85个
**浣跨敤鍦烘櫙锛?*
**使用场景:**
- 查看全局API架构
- 避免路由冲突
- 快速查找某个功能的API端点
@@ -58,29 +75,36 @@
---
### 5. 代码规范 ⭐⭐⭐⭐
**鏂囦欢锛?* `05-浠g爜瑙勮寖.md` 鈫?閲嶅懡鍚嶈嚜 `浠g爜瑙勮寖.md`锛堝凡瀛樺湪锛?18琛岋級
**文件:** `05-代码规范.md` → 重命名自 `代码规范.md`已存在818行
**鏍稿績鍐呭<EFBFBD>锛?*
**核心内容:**
- TypeScript编码规范
- React组件规范
- 鏂囦欢鍜岀洰褰曞懡鍚?- 浠g爜娉ㄩ噴瑙勮寖
- 文件和目录命名
- 代码注释规范
- 错误处理规范
- 日志记录规范
**已有内容,包含:**
- ESLint配置
- Prettier配置
- 璇︾粏鐨勭紪鐮佽<EFBFBD>鑼?
- 详细的编码规范
---
### 6. Git鎻愪氦瑙勮寖 猸愨瓙猸愨瓙猸?鉁?宸插畬鎴?**鏂囦欢锛?* `06-Git鎻愪氦瑙勮寖.md`
### 6. Git提交规范 ⭐⭐⭐⭐⭐ ✅ 已完成
**文件:** `06-Git提交规范.md`
**鏍稿績鍐呭<EFBFBD>锛?*
- 杩滅▼浠撳簱閰嶇疆锛圙itee锛?- Commit Message鏍煎紡瑙勮寖
**核心内容:**
- 远程仓库配置Gitee
- Commit Message格式规范
- 分支管理策略
- <EFBFBD>枃缂栫爜闂<EFBFBD><EFBFBD>喅鏂规<EFBFBD> 猸?閲嶈<E996B2>
- Git鍘嗗彶閲嶅啓涓庣淮鎶?- PR/MR瑙勮寖鍜屼唬鐮佸<E990AE>鏌ユ祦绋?- 甯歌<E794AF><EFBFBD><E99782>涓庢渶浣冲疄璺?
**鍖呭惈瀹炵敤宸ュ叿锛?*
- 中文编码问题解决方案 ⭐ 重要
- Git历史重写与维护
- PR/MR规范和代码审查流程
- 常见问题与最佳实践
**包含实用工具:**
- `fix-git-commit-messages.ps1` 脚本使用说明
- Git 别名配置
- 中文乱码修复完整流程
@@ -89,19 +113,22 @@
```
<type>(<scope>): <subject>
feat: 鏂板姛鑳? fix: Bug<EFBFBD><EFBFBD> docs: 鏂囨。
feat: 新功能 fix: Bug修复 docs: 文档
style: 格式 refactor: 重构 perf: 优化
test: 测试 chore: 构建 ci: CI/CD
```
---
### 7. 娴嬭瘯瑙勮寖 猸愨瓙猸?**鏂囦欢锛?* `07-娴嬭瘯瑙勮寖.md` 鈴?寰呭垱寤?
**鏍稿績鍐呭<EFBFBD>锛?*
### 7. 测试规范 ⭐⭐⭐
**文件:** `07-测试规范.md` ⏳ 待创建
**核心内容:**
- 单元测试规范
- 集成测试规范
- E2E测试规范
- 娴嬭瘯瑕嗙洊鐜囪<EFBFBD>姹?
- 测试覆盖率要求
**测试覆盖率要求:**
- 核心业务逻辑≥80%
- 工具函数≥90%
@@ -109,63 +136,83 @@ test: 测试 chore: 构建 ci: CI/CD
---
## 馃幆 瑙勮寖浼樺厛绾?
## 🎯 规范优先级
### P0 - 必须遵守
- 鉁?鏁版嵁搴撹<E690B4>璁¤<E79281>鑼?- 鉁?API璁捐<E79281>瑙勮寖
- 鉁?Git鎻愪氦瑙勮寖锛圕ommit Message锛?
- ✅ 数据库设计规范
- ✅ API设计规范
- ✅ Git提交规范Commit Message
### P1 - 强烈建议
- 鉁?浠g爜瑙勮寖锛圱ypeScript/React锛?- 鉁?閿欒<E996BF>澶勭悊瑙勮寖
- 鉁?鏃ュ織璁板綍瑙勮寖
- ✅ 代码规范TypeScript/React
- ✅ 错误处理规范
- ✅ 日志记录规范
### P2 - 建议遵守
- 鈿?娴嬭瘯瑙勮寖
- 鈿?鏂囨。娉ㄩ噴瑙勮寖
- 鈿?鎬ц兘浼樺寲瑙勮寖
- ⚪ 测试规范
- ⚪ 文档注释规范
- ⚪ 性能优化规范
---
## 馃攳 蹇<>€熸煡鎵?
**鎴戣<E98EB4>璁捐<E79281>鏁版嵁搴撹〃锛?* 鈫?`01-鏁版嵁搴撹<E690B4>璁¤<E79281>鑼?md`
**鎴戣<EFBFBD>璁捐<EFBFBD>API鎺ュ彛锛?* 鈫?`02-API璁捐<E79281>瑙勮寖.md`
**鎴戣<EFBFBD>鏌ョ湅鍏ㄥ眬鏁版嵁鏋舵瀯锛?* 鈫?`03-鏁版嵁搴撳叏灞€瑙嗗浘.md` 鉁?
**鎴戣<EFBFBD>鏌ョ湅鍏ㄥ眬API璺<EFBFBD>敱锛?* 鈫?`04-API璺<49>敱鎬昏<E98EAC>.md` 鉁?
**鎴戣<EFBFBD>缂栧啓浠爜锛?* 鈫?`05-浠g爜瑙勮寖.md` 鉁?
**鎴戣<EFBFBD>鎻愪氦浠爜锛?* 鈫?`06-Git鎻愪氦瑙勮寖.md` 鉁?
**鎴戣<EFBFBD>喅涓<EFBFBD>枃涔辩爜锛?* 鈫?`06-Git鎻愪氦瑙勮寖.md` (绗?鑺? 鉁?
**鎴戣<EFBFBD>閰嶇疆杩滅▼浠撳簱锛?* 鈫?`06-Git鎻愪氦瑙勮寖.md` (绗?鑺? 鉁?
**鎴戣<EFBFBD>缂栧啓娴嬭瘯锛?* 鈫?`07-娴嬭瘯瑙勮寖.md`
## 🔍 快速查找
**我要设计数据库表:**`01-数据库设计规范.md`
**我要设计API接口**`02-API设计规范.md`
**我要查看全局数据架构:**`03-数据库全局视图.md`
**我要查看全局API路由**`04-API路由总览.md`
**我要编写代码:**`05-代码规范.md`
**我要提交代码:**`06-Git提交规范.md`
**我要解决中文乱码:**`06-Git提交规范.md` (第4节) ✅
**我要配置远程仓库:**`06-Git提交规范.md` (第1节) ✅
**我要编写测试:**`07-测试规范.md`
---
## 鈿狅笍 杩濆弽瑙勮寖鐨勫悗鏋?
## ⚠️ 违反规范的后果
### 数据库设计不规范
- 鉂?Schema娣蜂贡锛屾ā鍧楄€﹀悎
- 鉂?鏃犳硶瀹炵幇妯″潡鐙<E6BDA1>珛閮ㄧ讲
- 鉂?鏁版嵁杩佺Щ鍥伴毦
- Schema混乱,模块耦合
- ❌ 无法实现模块独立部署
- ❌ 数据迁移困难
### API璁捐<EFBFBD>涓嶈<EFBFBD>鑼?- 鉂?鍓嶅悗绔<E68297><E7BB94>鎺ュ洶闅?- 鉂?API鏂囨。娣蜂贡
- 鉂?鐗堟湰鍗囩骇鍥伴毦
### API设计不规范
- ❌ 前后端对接困难
- ❌ API文档混乱
- ❌ 版本升级困难
### 代码不规范
- ❌ 代码可读性差
- ❌ 维护成本高
- ❌ Bug率上升
### 浠爜涓嶈<E6B693>鑼?- 鉂?浠爜鍙<E7889C><E98D99>у
- 鉂?缁存姢鎴愭湰楂?- 鉂?Bug鐜囦笂鍗?
---
## 📝 规范更新流程
1. 鎻愬嚭瑙勮寖鍙樻洿闇€姹傦紙Issue鎴朠R锛?2. 鍥㈤槦璁ㄨ<E79281>鍜岃瘎瀹?3. 鏇存柊瑙勮寖鏂囨。
1. 提出规范变更需求Issue或PR
2. 团队讨论和评审
3. 更新规范文档
4. 通知全员
5. 閫愭<EFBFBD>杩佺Щ鏃т唬鐮?
5. 逐步迁移旧代码
---
## 🔗 相关工具
**代码检查:**
- ESLint锛圝avaScript/TypeScript锛?- Prettier锛堜唬鐮佹牸寮忓寲锛?- Stylelint锛圕SS锛?
- ESLintJavaScript/TypeScript
- Prettier代码格式化
- StylelintCSS
**提交检查:**
- Husky锛圙it Hooks锛?- Commitlint锛圕ommit Message妫€鏌ワ級
- HuskyGit Hooks
- CommitlintCommit Message检查
**数据库:**
- Prisma锛圤RM + Migration锛?- pgAdmin锛堟暟鎹<E69A9F>簱绠悊锛?
- PrismaORM + Migration
- pgAdmin数据库管理
---
**最后更新:** 2025-11-06