新增地区-知识库绑定管理功能,支持增删改查操作 - 添加 V3 API 路由层:area-datasets 相关接口 - 添加 API 客户端:area-datasets.ts - 添加自定义 Hook:use-area-dataset-config.ts - 添加管理组件:area-dataset-config.tsx - 修复路由冲突问题,删除重复的 .ts 路由文件 - 更新 dataset-manager 页面,添加 Tabs 导航 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
20 KiB
Dify 模块 API 接口文档
版本:2.3 更新时间:2025-01-22 基础路径:
/api/v3
目录
- 更新知识库绑定
- 删除知识库绑定
- [检查用户知识库访问权限](#8- 对话应用管理接口
- 获取可用的对话应用列表
- 获取默认对话应用
概述
Dify 模块提供 AI 对话和知识库管理功能。本文档主要描述地区-知识库绑定管理相关接口。
核心概念
| 概念 | 说明 |
|---|---|
| 地区(area) | 用户所属地区,如:梅州、云浮、揭阳、潮州 |
| 知识库绑定 | 将 Dify 平台的知识库与特定地区关联,控制用户可访问的知识库范围 |
| 公共知识库 | is_public=true 的知识库,所有地区用户均可访问(如省级知识库) |
| 默认知识库 | is_default=true 的知识库,该地区用户的首选知识库 |
业务规则
- 普通用户(common)只能访问本地区绑定的知识库 + 公共知识库
- 市级管理员(admin)只能访问本地区绑定的知识库 + 公共知识库,可编辑本地区知识库内容
- 省级管理员(provincial_admin)可以访问和管理所有地区的知识库
- 只有省级管理员可以管理知识库绑定(增删改查绑定关系)
- 同一地区不能重复绑定同一知识库
- 删除为软删除,可恢复
权限说明
权限键定义(无通配符)
| 权限键 | 说明 | 适用角色 |
|---|---|---|
dify:chat:use |
使用 AI 对话 | common, provincial_admin, admin |
dify:conversation:read |
查看对话历史(仅自己) | common, provincial_admin, admin |
dify:conversation:delete |
删除对话(仅自己) | common, provincial_admin, admin |
dify:message:feedback |
消息反馈 | common, provincial_admin, admin |
dify:dataset:read |
查看知识库列表 | common, admin, provincial_admin |
dify:dataset:write |
编辑知识库内容 | admin(仅本地区), provincial_admin(全部) |
dify:dataset:manage |
管理知识库绑定(增删改查) | provincial_admin(仅省级管理员) |
dify:file:read |
下载/预览文件 | common, provincial_admin, admin |
dify:file:upload |
上传文件 | common, provincial_admin, admin |
角色权限矩阵
| 接口 | common | admin(市级管理员) | provincial_admin(省级管理员) |
|---|---|---|---|
| 获取用户可访问的知识库 | ✅ 本地区+公共 | ✅ 本地区+公共 | ✅ 全部 |
| 编辑知识库内容 | ❌ | ✅ 仅本地区 | ✅ 全部 |
| 获取所有绑定列表(管理) | ❌ | ❌ | ✅ |
| 创建/更新/删除绑定 | ❌ | ❌ | ✅ |
| 检查访问权限 | ✅ | ✅ | ✅ |
数据范围说明
| 数据范围 | 代码值 | 说明 |
|---|---|---|
| 全部 | ALL |
可访问所有地区数据(仅 provincial_admin) |
| 本地区 | DEPT |
只能访问本地区数据 + 公共数据(common, admin) |
| 仅自己 | SELF |
只能操作自己的数据(对话历史) |
安全设计
1. 对话数据越权防护
问题:用户 A 不能查看/删除用户 B 的对话
解决方案:
- Dify 端隔离:请求时强制注入
user参数为当前登录用户的username,无法伪造 - 本地数据库隔离:
dify_conversation表的操作都带user_id条件
-- 删除对话时的 SQL
UPDATE dify_conversation
SET deleted_at = CURRENT_TIMESTAMP
WHERE user_id = $1 AND conversation_id = $2 -- 必须是自己的
2. 知识库数据范围控制
问题:普通用户和市级管理员不能访问其他地区的知识库
解决方案:
# 根据用户角色控制数据范围
if user_role == "provincial_admin":
# 仅省级管理员返回所有知识库
else:
# 市级管理员和普通用户:只返回本地区 + 公共知识库
WHERE area = {user_area} OR is_public = true
3. 请求伪造防护
问题:用户伪造请求参数访问他人数据
解决方案:
- 所有用户身份信息从 JWT Token 解析,不信任请求参数
user参数强制覆盖,不允许前端传入
# process_request_body 中
body_data['user'] = username # 强制使用当前用户
地区知识库管理接口
1. 获取当前用户可访问的知识库
根据当前登录用户的地区和角色,返回可访问的知识库列表。
请求
GET /api/v3/dify/area-datasets/my
请求头
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Authorization | string | 是 | Bearer {token} |
数据范围控制
| 角色 | 返回数据 |
|---|---|
| common(普通员工) | 用户所属地区的知识库 + 公共知识库 |
| admin(市级管理员) | 用户所属地区的知识库 + 公共知识库 |
| provincial_admin(省级管理员) | 所有地区的知识库 |
响应
{
"code": 0,
"message": "success",
"data": {
"data": [
{
"id": 1,
"area": "省级",
"dataset_id": "fd680642-4493-416b-b592-972c69b3f595",
"dataset_name": "省级法务知识库",
"dataset_description": "全省通用法务知识库",
"is_default": false,
"is_public": true,
"sort_order": 0,
"status": 1,
"created_at": "2025-01-22T10:00:00",
"updated_at": "2025-01-22T10:00:00"
},
{
"id": 2,
"area": "梅州",
"dataset_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"dataset_name": "梅州法务知识库",
"dataset_description": "梅州地区专用知识库",
"is_default": true,
"is_public": false,
"sort_order": 10,
"status": 1,
"created_at": "2025-01-22T10:30:00",
"updated_at": "2025-01-22T10:30:00"
}
],
"total": 2,
"user_area": "梅州",
"user_role": "common"
}
}
响应字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| data.data | array | 知识库列表 |
| data.total | int | 知识库总数 |
| data.user_area | string | 当前用户所属地区 |
| data.user_role | string | 当前用户角色 |
错误响应
| HTTP 状态码 | 错误信息 | 说明 |
|---|---|---|
| 400 | 用户未设置地区,无法获取知识库列表 | 用户 area 字段为空(非管理员) |
| 401 | JWT 认证失败 | Token 无效或过期 |
| 403 | Permission denied | 无 dify:dataset:read 权限 |
2. 获取所有知识库绑定列表(管理员)
获取系统中所有地区的知识库绑定记录,支持按地区筛选和分页。
权限要求:dify:dataset:manage(仅 provincial_admin)
请求
GET /api/v3/dify/area-datasets
请求头
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Authorization | string | 是 | Bearer {token} |
查询参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| area | string | 否 | - | 筛选地区,如:梅州 |
| only_enabled | boolean | 否 | true | 是否只返回启用的记录 |
| page | int | 否 | 1 | 页码,从 1 开始 |
| page_size | int | 否 | 20 | 每页数量,范围 1-100 |
请求示例
curl -X GET "http://localhost:8000/api/v3/dify/area-datasets?area=梅州&page=1&page_size=20" \
-H "Authorization: Bearer {token}"
响应
{
"code": 0,
"message": "success",
"data": {
"data": [
{
"id": 2,
"area": "梅州",
"dataset_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"dataset_name": "梅州法务知识库",
"dataset_description": "梅州地区专用知识库",
"is_default": true,
"is_public": false,
"sort_order": 10,
"status": 1,
"created_by": 1,
"created_at": "2025-01-22T10:30:00",
"updated_by": null,
"updated_at": "2025-01-22T10:30:00"
}
],
"total": 1,
"page": 1,
"page_size": 20,
"has_more": false
}
}
3. 获取可用地区列表
获取系统中所有可用的地区列表,用于管理员创建绑定时选择地区。
权限要求:dify:dataset:manage
请求
GET /api/v3/dify/area-datasets/areas
响应
{
"code": 0,
"message": "success",
"data": {
"data": ["云浮", "揭阳", "梅州", "潮州"]
}
}
4. 获取知识库绑定详情
根据绑定记录 ID 获取详情。
权限要求:dify:dataset:manage
请求
GET /api/v3/dify/area-datasets/{dataset_bind_id}
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| dataset_bind_id | int | 是 | 绑定记录 ID |
响应
{
"code": 0,
"message": "success",
"data": {
"data": {
"id": 2,
"area": "梅州",
"dataset_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"dataset_name": "梅州法务知识库",
"dataset_description": "梅州地区专用知识库",
"is_default": true,
"is_public": false,
"sort_order": 10,
"status": 1,
"created_by": 1,
"created_at": "2025-01-22T10:30:00",
"updated_by": null,
"updated_at": "2025-01-22T10:30:00"
}
}
}
5. 创建知识库绑定
将 Dify 知识库绑定到指定地区。
权限要求:dify:dataset:manage
请求
POST /api/v3/dify/area-datasets
请求体
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| area | string | 是 | - | 地区名称(1-50字符) |
| dataset_id | string | 是 | - | Dify 知识库 ID(1-100字符) |
| dataset_name | string | 是 | - | 知识库名称(1-255字符) |
| dataset_description | string | 否 | null | 知识库描述 |
| is_default | boolean | 否 | false | 是否为该地区默认知识库 |
| is_public | boolean | 否 | false | 是否对所有地区公开 |
| sort_order | int | 否 | 0 | 排序顺序,越小越靠前 |
请求示例
curl -X POST "http://localhost:8000/api/v3/dify/area-datasets" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"area": "梅州",
"dataset_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"dataset_name": "梅州法务知识库",
"dataset_description": "梅州地区专用知识库",
"is_default": true,
"is_public": false,
"sort_order": 10
}'
响应
{
"code": 0,
"message": "success",
"data": {
"data": {
"id": 2,
"area": "梅州",
"dataset_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"dataset_name": "梅州法务知识库",
"dataset_description": "梅州地区专用知识库",
"is_default": true,
"is_public": false,
"sort_order": 10,
"status": 1,
"created_at": "2025-01-22T10:30:00"
},
"message": "创建成功"
}
}
错误响应
| HTTP 状态码 | 错误信息 | 说明 |
|---|---|---|
| 400 | 地区 '梅州' 已绑定知识库 'xxx' | 重复绑定 |
| 422 | Validation Error | 参数校验失败 |
6. 更新知识库绑定
更新知识库绑定信息,支持部分更新。
权限要求:dify:dataset:manage
请求
PUT /api/v3/dify/area-datasets/{dataset_bind_id}
请求体
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| dataset_name | string | 否 | 知识库名称 |
| dataset_description | string | 否 | 知识库描述 |
| is_default | boolean | 否 | 是否默认 |
| is_public | boolean | 否 | 是否公开 |
| sort_order | int | 否 | 排序顺序 |
| status | int | 否 | 状态:1=启用, 0=禁用 |
响应
{
"code": 0,
"message": "success",
"data": {
"data": {
"id": 2,
"area": "梅州",
"dataset_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"dataset_name": "梅州法务知识库(更新)",
"is_default": true,
"sort_order": 5,
"status": 1,
"updated_at": "2025-01-22T11:00:00"
},
"message": "更新成功"
}
}
7. 删除知识库绑定
软删除知识库绑定记录。
权限要求:dify:dataset:manage
请求
DELETE /api/v3/dify/area-datasets/{dataset_bind_id}
响应
{
"code": 0,
"message": "success",
"data": {
"message": "删除成功"
}
}
8. 检查用户知识库访问权限
检查当前用户是否有权访问指定的 Dify 知识库。
权限要求:dify:dataset:read
请求
GET /api/v3/dify/area-datasets/check/{dataset_id}
路径参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| dataset_id | string | 是 | Dify 知识库 ID |
响应(有权限)
{
"code": 0,
"message": "success",
"data": {
"has_access": true,
"user_area": "梅州",
"dataset_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab"
}
}
响应(无权限)
{
"code": 0,
"message": "success",
"data": {
"has_access": false,
"user_area": "梅州",
"dataset_id": "xyz-not-allowed"
}
}
错误码说明
HTTP 状态码
| 状态码 | 说明 |
|---|---|
| 200 | 请求成功 |
| 400 | 请求参数错误 |
| 401 | 未认证或 Token 无效 |
| 403 | 权限不足 |
| 404 | 资源不存在 |
| 422 | 参数校验失败 |
| 500 | 服务器内部错误 |
业务错误码
| code | 说明 |
|---|---|
| 0 | 成功 |
| -1 | 通用错误 |
数据字典
dify_area_dataset 表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | int | 主键 ID |
| area | varchar(50) | 地区名称 |
| dataset_id | varchar(100) | Dify 知识库 ID |
| dataset_name | varchar(255) | 知识库名称 |
| dataset_description | text | 知识库描述 |
| is_default | boolean | 是否为该地区默认知识库 |
| is_public | boolean | 是否对所有地区公开 |
| sort_order | int | 排序顺序,越小越靠前 |
| status | smallint | 状态:1=启用, 0=禁用 |
| created_by | int | 创建人 ID |
| created_at | timestamp | 创建时间 |
| updated_by | int | 更新人 ID |
| updated_at | timestamp | 更新时间 |
| deleted_at | timestamp | 删除时间(软删除) |
地区枚举值
| 值 | 说明 |
|---|---|
| 梅州 | 梅州地区 |
| 云浮 | 云浮地区 |
| 揭阳 | 揭阳地区 |
| 潮州 | 潮州地区 |
| 省级 | 省级(用于公共知识库) |
使用示例
场景1:管理员配置知识库
# 1. 创建省级公共知识库(所有用户可见)
curl -X POST "/api/v3/dify/area-datasets" \
-H "Authorization: Bearer {admin_token}" \
-d '{
"area": "省级",
"dataset_id": "省级知识库ID",
"dataset_name": "省级法务知识库",
"is_public": true,
"sort_order": 0
}'
# 2. 为各地区创建专属知识库(仅该地区用户可见)
curl -X POST "/api/v3/dify/area-datasets" \
-d '{"area": "梅州", "dataset_id": "梅州知识库ID", "dataset_name": "梅州法务知识库", "is_default": true}'
curl -X POST "/api/v3/dify/area-datasets" \
-d '{"area": "云浮", "dataset_id": "云浮知识库ID", "dataset_name": "云浮法务知识库", "is_default": true}'
场景2:普通用户获取可访问的知识库
# 梅州用户(common 角色)
curl -X GET "/api/v3/dify/area-datasets/my" \
-H "Authorization: Bearer {meizhou_user_token}"
# 返回:省级公共知识库 + 梅州专属知识库(2条)
场景3:省级管理员获取所有知识库
# 省级管理员(provincial_admin 角色)
curl -X GET "/api/v3/dify/area-datasets/my" \
-H "Authorization: Bearer {provincial_admin_token}"
# 返回:所有地区的知识库(包括梅州、云浮、揭阳、潮州、省级)
场景4:前端调用 Dify API 前检查权限
# 检查用户是否有权访问某个知识库
curl -X GET "/api/v3/dify/area-datasets/check/某知识库ID" \
-H "Authorization: Bearer {token}"
# 根据 has_access 字段决定是否允许调用 Dify API
9. 对话应用管理接口
9.1 获取可用的对话应用列表
接口: GET /api/v3/dify/chat-apps
权限: dify:chat:use
说明: 获取当前实例配置的所有对话应用列表,供前端切换使用。
请求示例:
curl -X GET "http://localhost:8000/api/v3/dify/chat-apps" \
-H "Authorization: Bearer <token>"
Response Body: success (data)
{
"code": 200,
"msg": "OK",
"data": {
"data": [
{
"app_id": "app-xxx",
"app_name": "AI法务助手",
"description": "通用法律咨询助手",
"is_default": true
},
{
"app_id": "app-yyy",
"app_name": "合同审查助手",
"description": "专业合同分析",
"is_default": false
}
],
"total": 2
}
}
字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
app_id |
string | 对话应用 ID |
app_name |
string | 对话应用名称 |
description |
string | 应用描述 |
is_default |
boolean | 是否为默认应用 |
9.2 获取默认对话应用
接口: GET /api/v3/dify/chat-apps/default
权限: dify:chat:use
说明: 获取当前配置的默认对话应用。
请求示例:
curl -X GET "http://localhost:8000/api/v3/dify/chat-apps/default" \
-H "Authorization: Bearer <token>"
Response Body: success (data)
{
"code": 200,
"msg": "OK",
"data": {
"data": {
"app_id": "app-xxx",
"app_name": "AI法务助手",
"description": "通用法律咨询助手",
"is_default": true
}
}
}
10. 对话应用多实例支持
10.1 配置方式
在 config/env.{port} 配置文件中添加 DIFY_CHAT_APPS 配置项:
格式:
DIFY_CHAT_APPS=app_id:api_key:app_name:description|app_id2:api_key2:app_name2:description
**说明**:
- 多个应用用 `|` 分隔
- 每个应用格式:`app_id`:`api_key`:`app_name`:`description`
- 第一个应用为默认应用
**示例**:
```ini
DIFY_CHAT_APPS=app-dmYZISz60ZGQHlJAPHmngoZZ:app-dmYZISz60ZGQHlJAPHmngoZZ:AI法务助手:通用法律咨询助手|app-xxx:app-xxx:合同审查助手:专业合同分析
10.2 前端切换应用
发送对话消息时,可通过以下方式指定应用:
方式 1:请求头(推荐)
axios.post('/api/dify/chat/chat-messages', data, {
headers: {
'Authorization': 'Bearer {token}',
'X-Dify-App-Id': 'app-xxx' // 指定应用 ID
}
})
方式 2:查询参数
axios.post('/api/dify/chat/chat-messages?app_id=app-xxx', data, {
headers: {
'Authorization': 'Bearer {token}'
}
})
使用默认应用:
不指定 X-Dify-App-Id 或 app_id 时,使用配置文件中的第一个应用作为默认应用。
10.3 端口多实例特性
本系统的特点是端口多实例部署架构,每个端口读取对应的配置文件:
| 端口 | 配置文件 | 默认对话应用 |
|---|---|---|
| 8073 | config/env.8073 |
梅州实例的对话应用 |
| 8000 | config/env.8000 |
云浮实例的对话应用 |
| 8001 | config/env.8001 |
揭阳实例的对话应用 |
| 8002 | config/env.8002 |
潮州实例的对话应用 |
因此,前端请求不同端口时,会获得不同的对话应用列表:
// 请求梅州实例
GET http://172.16.0.55:8073/api/v3/dify/chat-apps
// 返回梅州配置: [梅州法务助手, 梅州合同审查]
// 请求云浮实例
GET http://172.16.0.55:8000/api/v3/dify/chat-apps
// 返回云浮配置: [云浮法务助手, 云浮合同审查]
这种设计实现了区域间的业务隔离,无需后端代码判断,完全由配置驱动。
11. 更新日志
| 版本 | 日期 | 说明 |
|---|---|---|
| 2.3 | 2025-01-22 | 新增对话应用多实例支持,支持配置多个对话应用供前端切换 |
| 2.2 | 2025-01-22 | 修正角色权限:市级管理员(admin)只能访问本地区,省级管理员(provincial_admin)可访问全部;知识库绑定管理仅限省级管理员 |
| 2.1 | 2025-01-22 | 修正权限角色(去掉 area_admin),添加数据范围控制和越权防护说明 |
| 2.0 | 2025-01-22 | 新增地区-知识库绑定管理接口 |
| 1.0 | 2025-01-20 | 初始版本,Dify 代理接口 |