docs: refresh frontend integration notes

This commit is contained in:
wren
2026-05-06 09:42:29 +08:00
parent c54f84382b
commit b36e102aa0
9 changed files with 218 additions and 3970 deletions
+34
View File
@@ -0,0 +1,34 @@
# 前端工程文档导航
> 最后整理:2026-05-04
> 说明:本目录主要存放 `new_doc_review` 前端实现、联调、部署、能力评估类文档。
## 当前优先阅读
- 权限子页映射规范:`new_doc_review/docs/route-alias-guidelines.md`
- PostgREST 迁移盘点:
- `new_doc_review/docs/PostgREST使用情况-后端API替代建议.md`
- `new_doc_review/docs/PostgREST请求模块清单.md`
- `new_doc_review/docs/PostgREST实际使用清单.md`
- 文档类型页面改造背景:`new_doc_review/docs/文档类型管理CRUD详细分析.md`
- 评查点域联调资料:`new_doc_review/docs/evaluation/`
- 部署与运行:`new_doc_review/docs/deployment-config.md``new_doc_review/docs/docker-deployment.md`
## 按主题分类
| 主题 | 重点文档 | 说明 |
|------|----------|------|
| 权限 / 会话 / 登录 | `RBAC路由权限集成说明.md``RBAC路由权限集成_修复说明.md``JWT_IMPLEMENTATION.md``统一登录流程_实施记录.md` | 登录、JWT、路由权限接入 |
| PostgREST 迁移 | `PostgREST使用情况-后端API替代建议.md``PostgREST请求模块清单.md``PostgREST实际使用清单.md``PostgREST未使用函数清单.md` | 哪些页面仍依赖 PostgREST、替代优先级 |
| 首页 / 数据首页 | `getHomeData_完整逻辑文档.md``home-api-analysis.md` | 首页数据获取与结构说明 |
| 文档类型 / 规则页 | `文档类型管理CRUD详细分析.md``attribute_type_frontend_integration.md``evaluation/` | 文档类型、评查点、属性类型联调 |
| 合同模板 / 起草 | `contract-drafting-*.md``contract-draft-*.md` | 合同模板搜索、列表、起草与历史重构记录 |
| Dify / 智能助手 | `dify-proxy-backend-integration.md``new-dify/``Token管理架构优化总结.md` | 智能助手、代理接入、Token 管理 |
| 文件 / 文档能力 | `minio-docx-extraction-fix.md``docxtemplater-placeholder-extraction.md``react-pdf功能总结.md` | 文件处理、占位符提取、PDF 能力 |
| 部署 / 运行维护 | `deployment-config.md``deployment-checklist.md``docker-deployment.md``postgresql-backup-guide.md` | 环境部署与备份 |
## 使用约束
- 这里偏前端实现细节,不替代 `docs/` 下的项目主文档
- 涉及当前主链路的事实判断,优先对照 `docs/HANDOFF.md``docs/接口/README.md`
- 临时排障文档若已失效,应合并进正式文档后删除,不再继续堆积“紧急说明”类文件
-398
View File
@@ -1,398 +0,0 @@
# 🚨 紧急:前端Dify集成问题修复指南
## 问题现状
**当前错误**
```javascript
// ❌ 错误的Authorization头
Authorization: Bearer app-lHn5EmeACIaLjG9yz0rYIFfM // 这是Dify API Key,不是JWT
// ❌ 错误的user字段
user: "user_34a1d450-6a24-4db7-b1e7-8dd7c0876f14:sess_3z84y7dtuhr" // UUID格式
```
**导致的问题**
1. 无法加载历史对话记录(user不匹配)
2. 对话没有按用户隔离(所有人共享对话)
3. 安全问题(API Key暴露在前端)
---
## 🎯 必须修改的3个地方
### 修改1: Authorization头 - 使用JWT替代Dify API Key
#### ❌ 旧代码(错误)
```typescript
// app/services/dify-client.server.ts 或类似文件
const DIFY_API_KEY = "app-lHn5EmeACIaLjG9yz0rYIFfM";
async function callDifyAPI(endpoint: string, data: any) {
const response = await fetch(`${DIFY_BASE_URL}${endpoint}`, {
headers: {
'Authorization': `Bearer ${DIFY_API_KEY}`, // ❌ 错误!暴露API Key
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
```
#### ✅ 新代码(正确)
```typescript
// app/services/dify-client.server.ts
// 1. 移除DIFY_API_KEY配置
// const DIFY_API_KEY = "..."; // 删除这行
// 2. 从用户session获取JWT
import { getUserSession } from "~/api/login/auth.server";
async function callDifyAPI(request: Request, endpoint: string, data: any) {
// 获取JWT
const { frontendJWT } = await getUserSession(request);
if (!frontendJWT) {
throw new Error("未登录,请先登录");
}
// 使用JWT作为Authorization头
const response = await fetch(`http://172.16.0.55:8000/dify${endpoint}`, {
headers: {
'Authorization': `Bearer ${frontendJWT}`, // ✅ 正确!使用JWT
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
```
### 修改2: 请求URL - 指向FastAPI代理而非直连Dify
#### ❌ 旧代码(错误)
```typescript
// 直连Dify API
const DIFY_BASE_URL = "http://nas.7bm.co:12980/v1";
// 示例:获取会话列表
const response = await fetch(
`${DIFY_BASE_URL}/conversations?user=${user}&limit=100`,
// ...
);
```
#### ✅ 新代码(正确)
```typescript
// 通过FastAPI代理访问Dify
const API_BASE_URL = "http://172.16.0.55:8000"; // FastAPI地址
// 示例:获取会话列表
const response = await fetch(
`${API_BASE_URL}/dify/conversations?limit=100`, // ✅ 走/dify代理,不传user
{
headers: {
'Authorization': `Bearer ${frontendJWT}` // ✅ 使用JWT
}
}
);
```
### 修改3: user字段 - 完全移除,让后端自动添加
#### ❌ 旧代码(错误)
```typescript
// 生成UUID格式的user
function generateUserId() {
return `user_${crypto.randomUUID()}:sess_${randomString()}`;
}
// 发送消息
const data = {
query: "你好",
user: generateUserId(), // ❌ 错误!UUID格式
conversation_id: null,
response_mode: "streaming",
inputs: {}
};
```
#### ✅ 新代码(正确)
```typescript
// 完全不传user字段,后端会自动添加JWT的username
const data = {
query: "你好",
// user字段完全不传! ✅ 正确
conversation_id: null,
response_mode: "streaming",
inputs: {}
};
```
---
## 📝 完整的修改示例
### 示例1: 获取会话列表
#### ❌ 旧代码
```typescript
// app/routes/api.conversations.tsx
export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
const user = url.searchParams.get("user") || generateUserId();
const limit = url.searchParams.get("limit") || "100";
const response = await fetch(
`http://nas.7bm.co:12980/v1/conversations?user=${user}&limit=${limit}`,
{
headers: {
'Authorization': `Bearer app-lHn5EmeACIaLjG9yz0rYIFfM`, // ❌ Dify API Key
'Content-Type': 'application/json'
}
}
);
return json(await response.json());
}
```
#### ✅ 新代码
```typescript
// app/routes/api.conversations.tsx
import { getUserSession } from "~/api/login/auth.server";
export async function loader({ request }: LoaderFunctionArgs) {
// 1. 获取JWT
const { frontendJWT } = await getUserSession(request);
if (!frontendJWT) {
return json({ error: "未登录" }, { status: 401 });
}
// 2. 调用FastAPI代理(不传user,后端自动添加)
const url = new URL(request.url);
const limit = url.searchParams.get("limit") || "100";
const response = await fetch(
`http://172.16.0.55:8000/dify/conversations?limit=${limit}`, // ✅ 走代理
{
headers: {
'Authorization': `Bearer ${frontendJWT}`, // ✅ 使用JWT
'Content-Type': 'application/json'
}
}
);
return json(await response.json());
}
```
### 示例2: 发送消息
#### ❌ 旧代码
```typescript
// app/routes/api.chat-messages.tsx
export async function action({ request }: ActionFunctionArgs) {
const body = await request.json();
const response = await fetch(
`http://nas.7bm.co:12980/v1/chat-messages`,
{
method: 'POST',
headers: {
'Authorization': `Bearer app-lHn5EmeACIaLjG9yz0rYIFfM`, // ❌ Dify API Key
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: body.query,
user: body.user || generateUserId(), // ❌ UUID格式
conversation_id: body.conversation_id,
response_mode: "streaming",
inputs: body.inputs || {}
})
}
);
return new Response(response.body, {
headers: { 'Content-Type': 'text/event-stream' }
});
}
```
#### ✅ 新代码
```typescript
// app/routes/api.chat-messages.tsx
import { getUserSession } from "~/api/login/auth.server";
export async function action({ request }: ActionFunctionArgs) {
// 1. 获取JWT
const { frontendJWT } = await getUserSession(request);
if (!frontendJWT) {
return json({ error: "未登录" }, { status: 401 });
}
// 2. 解析请求体
const body = await request.json();
// 3. 调用FastAPI代理(不传user,后端自动添加)
const response = await fetch(
`http://172.16.0.55:8000/dify/chat-messages`, // ✅ 走代理
{
method: 'POST',
headers: {
'Authorization': `Bearer ${frontendJWT}`, // ✅ 使用JWT
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: body.query,
// user字段完全不传 ✅ 后端自动添加
conversation_id: body.conversation_id,
response_mode: "streaming",
inputs: body.inputs || {}
})
}
);
return new Response(response.body, {
headers: { 'Content-Type': 'text/event-stream' }
});
}
```
---
## 🔍 检查清单
### 前端开发者必须检查的文件
1. **Dify客户端配置文件**
- 位置:`app/services/dify-client.server.ts` 或类似
- 检查:是否还有`DIFY_API_KEY`定义?(应该删除)
- 检查:是否还有`DIFY_BASE_URL = "http://nas.7bm.co:12980"`?(应改为FastAPI地址)
2. **API路由文件**
- 位置:`app/routes/api.*.tsx` 中所有与Dify相关的
- 检查:所有`fetch`调用是否指向`http://172.16.0.55:8000/dify/*`
- 检查:所有`Authorization`头是否使用`frontendJWT`
3. **user字段生成逻辑**
- 搜索关键字:`generateUserId`, `user_`, `crypto.randomUUID`
- 检查:是否还在生成UUID格式的user?(应该完全移除)
4. **环境变量配置**
- 位置:`.env``.env.local`
- 检查:是否还有`DIFY_API_KEY``NEXT_PUBLIC_APP_KEY`?(应该删除)
---
## 🧪 验证方法
修改完成后,使用浏览器开发者工具验证:
### 1. 检查Authorization头
打开 Network 标签,找到Dify相关请求:
**✅ 正确的请求头**
```
Request URL: http://172.16.0.55:8000/dify/conversations?limit=100
Request Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... (JWT格式,很长)
Content-Type: application/json
```
**❌ 错误的请求头**
```
Request URL: http://nas.7bm.co:12980/v1/conversations?user=xxx
Request Headers:
Authorization: Bearer app-lHn5EmeACIaLjG9yz0rYIFfM (Dify API Key,很短)
```
### 2. 检查请求体
对于POST请求(如发送消息):
**✅ 正确的请求体**
```json
{
"query": "你好",
"conversation_id": null,
"response_mode": "streaming",
"inputs": {}
}
```
注意:**没有user字段**
**❌ 错误的请求体**
```json
{
"query": "你好",
"user": "user_34a1d450-6a24-4db7-b1e7-8dd7c0876f14:sess_xxx",
"conversation_id": null,
"response_mode": "streaming",
"inputs": {}
}
```
### 3. 检查后端日志
修改后,后端日志应该显示:
```log
[INFO] Dify请求用户: admin (ID: 5, 路径: conversations)
[INFO] 自动添加user参数: admin
[INFO] 查询参数: {'user': 'admin', 'limit': '100'}
```
### 4. 检查Dify后台
在Dify管理界面的对话列表中,应该看到:
- 新对话的用户显示为:`admin`(或实际的username
- 不再是:`user_34a1d450...`
---
## ⚠️ 常见错误
### 错误1: 前端仍使用DIFY_API_KEY
**症状**Authorization头是`Bearer app-xxx`(短字符串)
**解决**:删除所有`DIFY_API_KEY`定义,改用`frontendJWT`
### 错误2: 前端直连Dify
**症状**:请求URL是`http://nas.7bm.co:12980/v1/...`
**解决**:所有URL改为`http://172.16.0.55:8000/dify/...`
### 错误3: 仍在传递UUID格式的user
**症状**:请求体包含`"user": "user_34a1d450..."`
**解决**:完全删除user字段,不要传递
### 错误4: JWT获取失败
**症状**`frontendJWT``null``undefined`
**解决**:检查`getUserSession`导入路径和session配置
---
## 📋 修改总结
| 项目 | 旧值 | 新值 |
|------|------|------|
| Authorization头 | `Bearer app-lHn5EmeACIaLjG9yz0rYIFfM` | `Bearer {frontendJWT}` |
| 请求URL | `http://nas.7bm.co:12980/v1/*` | `http://172.16.0.55:8000/dify/*` |
| user字段 | `user_34a1d450-...` | 完全不传(后端自动添加) |
---
## 🎯 期望结果
修改完成后:
- ✅ 每个用户只能看到自己的对话记录
- ✅ Dify后台显示真实的username(如admin
- ✅ API Key不再暴露在前端
- ✅ 所有对话按用户隔离
- ✅ 历史对话记录正常加载
---
**紧急程度**: 🔴 高优先级
**预计修改时间**: 30-60分钟
**影响范围**: 所有Dify相关功能
**联系后端**: 如有疑问,请查看`docs/dify-frontend-user-field-guide.md`获取更多细节
+3 -3
View File
@@ -558,7 +558,7 @@ const wrongUsers = await getRoleUsers(3); // 数据库中不存在
"id": 41,
"route_path": "/rules",
"route_name": "Rules",
"route_title": "评查规则库",
"route_title": "规则管理",
"parent_id": null,
"icon": "ri-book-3-line",
"sort_order": 3,
@@ -833,7 +833,7 @@ sys_routes 表:仅存储页面路由(侧边栏菜单)
permissions 表:存储API操作权限(通过 route_id 关联到页面)
页面路由
├── 评查规则库 (/rules)
├── 规则管理 (/rules)
│ ├── [权限] 查看评查点分组列表 (GET /api/v3/evaluation-point-groups)
│ ├── [权限] 创建评查点分组 (POST /api/v3/evaluation-point-groups)
│ ├── [权限] 查看评查点规则列表 (GET /api/v3/evaluation-points)
@@ -880,7 +880,7 @@ interface Permission {
│ │
│ ☑ 系统概览 (/home) │
│ │
│ ☑ 评查规则库 (/rules) │
│ ☑ 规则管理 (/rules) │
│ ├─ ☑ 查看评查点分组列表 [GET] │
│ ├─ ☑ 创建评查点分组 [POST] │
│ ├─ ☑ 更新评查点分组 [PUT] │
+8 -5
View File
@@ -68,18 +68,21 @@
- `/config-lists/new` -> `/config-lists`
- `/prompts/new` -> `/prompts`
- `/rule-groups/new` -> `/rule-groups`
- `/rules/new` -> `/rules/list`
- `/rules/new` -> `/rules`
- `/documents/list` -> `/documents`
- `/documents/edit` -> `/documents`
- 模块内子页
- `/contract-template/search/results` -> `/contract-template/search`
- `/contract-template/detail/:id` -> `/contract-template`
- `/contract-draft/:id` -> `/contract-template`
- `/contract-template/detail/:id` -> `/contract-template/list`
- `/contract-draft/:id` -> `/contract-template/list`
- `/chat-with-llm/chat` -> `/chat-with-llm`
- `/chat-with-llm/dataset-manager` -> `/chat-with-llm`
- 历史兼容页
- `/reviewsTest` -> `/reviews`
- `/rulesTest/list` -> `/rules/list`
- `/rulesTest/detail` -> `/rules/list`
- `/rulesTest/list` -> `/rules`
- `/rulesTest/detail` -> `/rules`
---