# 知识库模块 - API 文档

> **版本**: v1.0  
> **最后更新**: 2026-02-25  
> **维护者**: 后端团队

> 🚧 Draft：本文件已对齐当前实现，细节持续补充。

---

## 📋 API 概述

### Base URL

```
开发: http://localhost:3001/api/v1
测试: https://test-api.example.com/api/v1
生产: https://api.example.com/api/v1
```

### 认证方式

- **类型**: Bearer Token (JWT)
- **Header**: `Authorization: Bearer <token>`

### 通用响应格式

**成功响应**:
```json
{
  "success": true,
  "data": {},
  "timestamp": "2026-01-09T00:00:00Z"
}
```

**错误响应**:
```json
{
  "success": false,
  "error": {
    "code": "KB_ERROR",
    "message": "错误信息"
  },
  "timestamp": "2026-01-09T00:00:00Z",
  "path": "/api/v1/knowledge-base/semantic-search",
  "method": "GET",
  "statusCode": 400
}
```

---

## 📌 接口数量汇总

- **总数**: 27
- **搜索**: 3
- **上传**: 1
- **文章**: 3
- **AI 问答**: 3
- **同步**: 9
- **统计**: 3
- **活动**: 6

## 📌 按域接口清单（编号）

1. 搜索
   - `GET /knowledge-base/search-suggestions`
   - `DELETE /knowledge-base/search-history`
   - `GET /knowledge-base/semantic-search`
2. 上传
   - `POST /knowledge-base/upload`
3. 文章
   - `POST /knowledge-base/articles`
   - `GET /knowledge-base/articles/:id`
   - `PUT /knowledge-base/articles/:id`
4. AI 问答
   - `POST /knowledge-base/ask`
   - `POST /knowledge-base/ask/:id/feedback`
   - `GET /knowledge-base/ask/history`
5. 同步
   - `POST /knowledge-base/sync/full`
   - `POST /knowledge-base/sync/delta`
   - `GET /knowledge-base/sync/tasks`
   - `GET /knowledge-base/sync/tasks/:taskId`
   - `GET /knowledge-base/sync/tasks/:taskId/skipped`
   - `GET /knowledge-base/sync/tasks/:taskId/processed`
   - `GET /knowledge-base/sync/tasks/:taskId/processing`
   - `GET /knowledge-base/sync/tasks/:taskId/failed`
   - `POST /knowledge-base/sync/tasks/:taskId/terminate`
6. 统计
   - `GET /knowledge-base/metrics`
   - `GET /knowledge-base/metrics/trend`
   - `GET /knowledge-base/metrics/top-queries`
7. 活动
   - `GET /knowledge-base/recently-visited`
   - `POST /knowledge-base/view/:type/:id`
   - `GET /knowledge-base/activity`
   - `GET /knowledge-base/user-analytics`
   - `GET /knowledge-base/unread-mentions`
   - `POST /knowledge-base/mentions/:id/read`

## 📚 API 列表（当前实现）

| 分类 | Method | Endpoint | 说明 | 权限 |
|------|--------|----------|------|------|
| 搜索 | GET | `/knowledge-base/search-suggestions` | 输入联想建议（轻量候选） | 需要登录 |
| 搜索 | DELETE | `/knowledge-base/search-history` | 删除最近搜索（单条/全部） | 需要登录 |
| 搜索 | GET | `/knowledge-base/semantic-search` | 语义/关键词/混合搜索 | 需要登录 |
| 上传 | POST | `/knowledge-base/upload` | 上传文件到 SharePoint 默认库 | 需要登录 |
| 文章 | POST | `/knowledge-base/articles` | 创建原生文章 | 需要登录 |
| 文章 | GET | `/knowledge-base/articles/:id` | 获取文章详情 | 需要登录 |
| 文章 | PUT | `/knowledge-base/articles/:id` | 保存文章 | 需要登录 |
| AI 问答 | POST | `/knowledge-base/ask` | RAG 问答 | 需要登录 |
| AI 问答 | POST | `/knowledge-base/ask/:id/feedback` | 提交问答反馈 | 需要登录 |
| AI 问答 | GET | `/knowledge-base/ask/history` | 获取问答历史 | 需要登录 |
| 同步 | POST | `/knowledge-base/sync/full` | 触发全量同步 | 需要登录 |
| 同步 | POST | `/knowledge-base/sync/delta` | 触发增量同步 | 需要登录 |
| 同步 | GET | `/knowledge-base/sync/tasks` | 获取同步任务列表 | 需要登录 |
| 同步 | GET | `/knowledge-base/sync/tasks/:taskId` | 获取同步任务状态 | 需要登录 |
| 同步 | GET | `/knowledge-base/sync/tasks/:taskId/skipped` | 获取同步任务跳过明细 | 需要登录 |
| 同步 | GET | `/knowledge-base/sync/tasks/:taskId/processed` | 获取同步任务已处理明细 | 需要登录 |
| 同步 | GET | `/knowledge-base/sync/tasks/:taskId/processing` | 获取同步任务处理中明细 | 需要登录 |
| 同步 | GET | `/knowledge-base/sync/tasks/:taskId/failed` | 获取同步任务失败明细 | 需要登录 |
| 同步 | POST | `/knowledge-base/sync/tasks/:taskId/terminate` | 手动终止同步任务 | 需要登录 |
| 统计 | GET | `/knowledge-base/metrics` | 指标概览 | 需要登录 |
| 统计 | GET | `/knowledge-base/metrics/trend` | 每日趋势 | 需要登录 |
| 统计 | GET | `/knowledge-base/metrics/top-queries` | 搜索热词 | 需要登录 |
| 活动 | GET | `/knowledge-base/recently-visited` | 最近访问 | 需要登录 |
| 活动 | POST | `/knowledge-base/view/:type/:id` | 记录浏览 | 需要登录 |
| 活动 | GET | `/knowledge-base/activity` | 活动动态 | 需要登录 |
| 活动 | GET | `/knowledge-base/user-analytics` | 用户统计 | 需要登录 |
| 活动 | GET | `/knowledge-base/unread-mentions` | 未读提及数 | 需要登录 |
| 活动 | POST | `/knowledge-base/mentions/:id/read` | 标记提及已读 | 需要登录 |

---

## 1. 搜索建议

### 请求

- **Endpoint**: `GET /knowledge-base/search-suggestions`
- **权限**: 需要登录
- **说明**: 用于搜索输入过程中的联想建议；不调用 RAGFlow，不写入搜索日志

**Query Parameters**:

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `q` | string | - | 当前输入关键词（必填，最少 2 字符） |
| `limit` | number | 8 | 返回条数（1-20） |

### 响应

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "items": [
      {
        "text": "请假流程",
        "source": "RECENT_SEARCH"
      },
      {
        "text": "请假审批制度",
        "source": "TOP_QUERY"
      },
      {
        "text": "请假申请操作手册",
        "source": "TITLE"
      }
    ]
  },
  "timestamp": "2026-02-25T00:00:00Z"
}
```

---

## 2. 删除最近搜索

### 请求

- **Endpoint**: `DELETE /knowledge-base/search-history`
- **权限**: 需要登录
- **说明**:
  - 不传 `query`：清空当前用户全部最近搜索
  - 传 `query`：删除当前用户该关键词最近搜索记录

**Query Parameters**:

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `query` | string | - | 可选，指定要删除的关键词 |

### 响应

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "deleted": 3
  },
  "timestamp": "2026-02-25T00:00:00Z"
}
```

---

## 3. 语义搜索

### 请求

- **Endpoint**: `GET /knowledge-base/semantic-search`
- **权限**: 需要登录
 - **说明**: 通过 RAGFlow 检索（文档/文章）+ SharePoint 文件夹元数据检索（文件夹），返回统一结果
 - **渲染约定**:
   - `snippet` 返回纯文本摘要；前端可基于查询词执行“命中片段裁剪 + 关键词高亮”，接口不返回 HTML 高亮内容
   - `previewContent`（可选）返回该结果可用于预览的扩展文本（由多个检索分片聚合），用于右侧预览面板“尽量完整展示”
   - `type=folder` 表示文件夹结果；前端需按“文件结果在上、文件夹结果在下”分组渲染

**Query Parameters**:

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `q` | string | - | 搜索关键词（必填） |
| `limit` | number | 20 | 返回条数 |
| `type` | string | `hybrid` | `keyword` / `semantic` / `hybrid` |
| `docType` | string | - | 文档类型过滤 |
| `authorityLevel` | string | - | 权威级别过滤 |

### 响应

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "string",
        "type": "document",
        "title": "Document Name",
        "webUrl": "https://...",
        "snippet": "string",
        "previewContent": "string",
        "score": 0.85,
        "docType": "POLICY",
        "docAuthorityLevel": "OFFICIAL",
        "lastModifiedAt": "2025-01-02T10:00:00Z",
        "createdBy": "Alice"
      },
      {
        "id": "string",
        "type": "folder",
        "title": "HR Policies",
        "webUrl": "https://...",
        "snippet": "/Shared Documents/Policies/HR Policies",
        "score": 0.85,
        "folderPath": "/Shared Documents/Policies/HR Policies",
        "lastModifiedAt": "2025-01-02T10:00:00Z"
      }
    ],
    "total": 1,
    "searchType": "hybrid",
    "responseTimeMs": 120
  },
  "timestamp": "2026-01-09T00:00:00Z"
}
```

---

## 8. 全量同步

### 请求

- **Endpoint**: `POST /knowledge-base/sync/full`
- **权限**: 需要登录
- **说明**: 异步触发全量同步任务，返回任务 ID

### 响应

**成功 (201 Created)**:
```json
{
  "success": true,
  "data": {
    "taskId": "uuid",
    "message": "全量同步任务已启动"
  },
  "message": "success"
}
```

---

## 8.1 增量同步

### 请求

- **Endpoint**: `POST /knowledge-base/sync/delta`
- **权限**: 需要登录
- **说明**: 基于 SharePoint Delta 的增量同步，仅处理变更文件与删除事件；游标缺失/失效时自动回退为全量同步

### 响应

**成功 (201 Created)**:
```json
{
  "success": true,
  "data": {
    "taskId": "uuid",
    "message": "增量同步任务已启动"
  },
  "message": "success"
}
```

---

## 8.2 终止同步任务

### 请求

- **Endpoint**: `POST /knowledge-base/sync/tasks/:taskId/terminate`
- **权限**: 需要登录
- **说明**: 仅对状态为 SYNCING 的任务生效，终止后状态标记为 FAILED

### 响应

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "taskId": "uuid",
    "totalItems": 10,
    "processedItems": 5,
    "failedItems": 1,
    "skippedItems": 0,
    "processedTokens": 1200,
    "processedChunks": 18,
    "status": "FAILED",
    "error": "已手动终止"
  },
  "message": "success"
}
```

---

## 9. 同步任务列表

### 请求

- **Endpoint**: `GET /knowledge-base/sync/tasks`
- **权限**: 需要登录

**Query Parameters**:

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `limit` | number | 20 | 返回条数（1-100） |
| `offset` | number | 0 | 偏移量 |

### 响应

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "uuid",
        "taskType": "FULL_SYNC",
        "triggerSource": "MANUAL_FULL",
        "status": "COMPLETED",
        "totalItems": 10,
        "processedItems": 9,
        "processingItems": 1,
        "failedItems": 0,
        "skippedItems": 1,
        "processedTokens": 2400,
        "processedChunks": 36,
        "error": null,
        "startedAt": "2026-02-04T09:03:31.090Z",
        "completedAt": "2026-02-04T09:03:53.782Z",
        "createdAt": "2026-02-04T09:03:31.090Z"
      }
    ],
    "total": 1
  },
  "message": "success"
}
```

---

## 10. 同步任务状态

### 请求

- **Endpoint**: `GET /knowledge-base/sync/tasks/:taskId`
- **权限**: 需要登录

### 响应

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "taskId": "uuid",
    "totalItems": 10,
    "processedItems": 9,
    "processingItems": 1,
    "failedItems": 0,
    "skippedItems": 1,
    "processedTokens": 2400,
    "processedChunks": 36,
    "status": "COMPLETED",
    "triggerSource": "MANUAL_FULL"
  },
  "message": "success"
}
```

---

## 11. 同步任务跳过明细

### 请求

- **Endpoint**: `GET /knowledge-base/sync/tasks/:taskId/skipped`
- **权限**: 需要登录

**Query Parameters**:

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `limit` | number | 20 | 返回条数（1-200） |
| `offset` | number | 0 | 偏移量 |

### 响应

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "uuid",
        "taskId": "uuid",
        "sourceType": "SP_DOCUMENT",
        "sourceId": "uuid",
        "filename": "env.dev.example",
        "fileExtension": "example",
        "mimeType": "application/octet-stream",
        "reason": "Unsupported file type",
        "createdAt": "2026-02-04T09:05:31.090Z"
      }
    ],
    "total": 1
  },
  "message": "success"
}
```

---

## 12. 同步任务已处理明细

### 请求

- **Endpoint**: `GET /knowledge-base/sync/tasks/:taskId/processed`
- **权限**: 需要登录

**Query Parameters**:

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `limit` | number | 20 | 返回条数（1-200） |
| `offset` | number | 0 | 偏移量 |

### 响应

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "uuid",
        "taskId": "uuid",
        "sourceType": "SP_DOCUMENT",
        "sourceId": "uuid",
        "filename": "Book.xlsx",
        "fileExtension": "xlsx",
        "mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "ragflowDocumentId": "ragflow-id",
        "tokenCount": 320,
        "chunkCount": 4,
        "sourceSizeBytes": 24576,
        "status": "COMPLETED",
        "createdAt": "2026-02-04T09:05:31.090Z"
      }
    ],
    "total": 1
  },
  "message": "success"
}
```

---

## 13. 同步任务处理中明细

### 请求

- **Endpoint**: `GET /knowledge-base/sync/tasks/:taskId/processing`
- **权限**: 需要登录

**Query Parameters**:

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `limit` | number | 20 | 返回条数（1-200） |
| `offset` | number | 0 | 偏移量 |

### 响应

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "uuid",
        "taskId": "uuid",
        "sourceType": "SP_DOCUMENT",
        "sourceId": "uuid",
        "filename": "Book.xlsx",
        "fileExtension": "xlsx",
        "mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "ragflowDocumentId": "ragflow-id",
        "tokenCount": 0,
        "chunkCount": 0,
        "sourceSizeBytes": 24576,
        "status": "PROCESSING",
        "createdAt": "2026-02-04T09:05:31.090Z"
      }
    ],
    "total": 1
  },
  "message": "success"
}
```

---

## 14. 同步任务失败明细

### 请求

- **Endpoint**: `GET /knowledge-base/sync/tasks/:taskId/failed`
- **权限**: 需要登录

**Query Parameters**:

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `limit` | number | 20 | 返回条数（1-200） |
| `offset` | number | 0 | 偏移量 |

### 响应

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "uuid",
        "taskId": "uuid",
        "sourceType": "SP_DOCUMENT",
        "sourceId": "uuid",
        "filename": "AI策略.pptx",
        "fileExtension": "pptx",
        "mimeType": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
        "error": "RAGFlow parse failed",
        "createdAt": "2026-02-04T09:05:31.090Z"
      }
    ],
    "total": 1
  },
  "message": "success"
}
```

---

## 2. 文件上传

### 请求

- **Endpoint**: `POST /knowledge-base/upload`
- **权限**: 需要登录（MVP 阶段不做权限过滤）
- **Content-Type**: `multipart/form-data`

**Form Data**:

| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `file` | File | ✅ | 上传文件 |

### 响应

**成功 (201 Created)**:
```json
{
  "success": true,
  "data": {
    "item": {
      "id": "string",
      "name": "Document Name.docx",
      "webUrl": "https://.../Document Name.docx",
      "size": 12345,
      "createdAt": "2025-01-01T10:00:00Z",
      "lastModifiedAt": "2025-01-02T10:00:00Z"
    }
  },
  "timestamp": "2026-01-09T00:00:00Z",
  "path": "/api/v1/knowledge-base/upload"
}
```

**错误响应**:

| HTTP状态码 | 错误码 | 说明 |
|-----------|--------|------|
| 400 | `KNOWLEDGE_BASE_VALIDATION_001` | 未上传文件 |
| 503 | `KNOWLEDGE_BASE_UPLOAD_FAILED` | SharePoint 上传失败 |

---

## 3. 原生文章

### 4.1 创建文章

- **Endpoint**: `POST /knowledge-base/articles`
- **Content-Type**: `application/json`

**Request Body**:
```json
{
  "title": "string",
  "content": "string"
}
```

> 说明：`content` 为 ProseMirror 文档 JSON 的序列化字符串。

**成功 (201 Created)**:
```json
{
  "success": true,
  "data": {
    "id": "uuid",
    "title": "示例标题",
    "content": "{\"type\":\"doc\",\"content\":[{\"type\":\"paragraph\",\"content\":[{\"type\":\"text\",\"text\":\"示例内容\"}]}]}",
    "status": "DRAFT",
    "createdById": "uuid",
    "createdAt": "2026-01-09T00:00:00Z",
    "updatedAt": "2026-01-09T00:00:00Z"
  },
  "message": "文章创建成功"
}
```

### 4.2 获取文章

- **Endpoint**: `GET /knowledge-base/articles/:id`

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "id": "uuid",
    "title": "示例标题",
    "content": "{\"type\":\"doc\",\"content\":[{\"type\":\"paragraph\",\"content\":[{\"type\":\"text\",\"text\":\"示例内容\"}]}]}",
    "status": "DRAFT"
  }
}
```

### 4.3 更新文章

- **Endpoint**: `PUT /knowledge-base/articles/:id`
- **Content-Type**: `application/json`

**Request Body**:
```json
{
  "title": "string",
  "content": "string"
}
```

> 说明：`content` 为 ProseMirror 文档 JSON 的序列化字符串。

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "id": "uuid",
    "title": "更新后的标题",
    "content": "{\"type\":\"doc\",\"content\":[{\"type\":\"paragraph\",\"content\":[{\"type\":\"text\",\"text\":\"更新后的内容\"}]}]}"
  },
  "message": "文章已保存"
}
```

---

## 4. AI 问答

### 4.1 发起问答

- **Endpoint**: `POST /knowledge-base/ask`
- **Content-Type**: `application/json`
- **说明**: 由 RAGFlow 生成答案并返回引用片段

**Request Body**:
```json
{
  "question": "string",
  "docType": "POLICY",
  "authorityLevel": "OFFICIAL"
}
```

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "id": "uuid",
    "answer": "string",
    "sources": [
      {
        "id": "string",
        "type": "document",
        "title": "string",
        "webUrl": "https://...",
        "snippet": "string",
        "authorityLevel": "OFFICIAL",
        "docType": "POLICY",
        "relevanceScore": 0.92
      }
    ],
    "confidence": 0.83,
    "metadata": {
      "modelUsed": "gpt-4o-mini",
      "tokensUsed": 1234,
      "cost": 0.01,
      "responseTimeMs": 800
    }
  },
  "timestamp": "2026-01-09T00:00:00Z"
}
```

**无可用来源时**：
- `sources` 为空数组
- `confidence` 为 `0`
- `answer` 返回固定提示（不调用 LLM）

### 4.2 提交反馈

- **Endpoint**: `POST /knowledge-base/ask/:id/feedback`
- **Content-Type**: `application/json`

**Request Body**:
```json
{
  "feedback": "THUMBS_UP",
  "comment": "string"
}
```

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "success": true
  },
  "message": "反馈已提交"
}
```

### 4.3 获取问答历史

- **Endpoint**: `GET /knowledge-base/ask/history`

**Query Parameters**:

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `limit` | number | 20 | 返回条数 |

**成功 (200 OK)**:
```json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "uuid",
        "question": "string",
        "answer": "string",
        "createdAt": "2026-01-09T00:00:00Z"
      }
    ]
  }
}
```
