From 6fd305eac99e742f368628021ca70face49fc8a6 Mon Sep 17 00:00:00 2001 From: lintsinghua Date: Thu, 4 Dec 2025 16:54:15 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复创建ZIP项目时缺少source_type字段的问题 - 修复LiteLLM模型名称被错误解析为effort参数的问题 - 修复登录/注册页面无法正确显示验证错误的问题 - 添加Windows导出PDF需要GTK依赖的说明文档 --- README.md | 28 +++++++++++++++++++ .../services/llm/adapters/litellm_adapter.py | 4 +++ frontend/src/pages/Login.tsx | 11 +++++++- frontend/src/pages/Register.tsx | 11 +++++++- frontend/src/shared/api/database.ts | 1 + 5 files changed, 53 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a6cbc98..4152a99 100644 --- a/README.md +++ b/README.md @@ -283,6 +283,34 @@ LLM_API_KEY=your_api_key:your_secret_key 获取地址:https://console.bce.baidu.com/qianfan/ +
+Windows 导出 PDF 报错怎么办? + +PDF 导出功能使用 WeasyPrint 库,在 Windows 系统上需要安装 GTK 依赖: + +**方法一:使用 MSYS2 安装(推荐)** +```bash +# 1. 下载并安装 MSYS2: https://www.msys2.org/ +# 2. 打开 MSYS2 终端,执行: +pacman -S mingw-w64-x86_64-pango mingw-w64-x86_64-gtk3 + +# 3. 将 MSYS2 的 bin 目录添加到系统 PATH 环境变量: +# C:\msys64\mingw64\bin +``` + +**方法二:使用 GTK3 Runtime 安装包** +1. 下载 GTK3 Runtime: https://github.com/nickvidal/gtk3-runtime/releases +2. 安装后将安装目录添加到系统 PATH + +**方法三:使用 Docker 部署(最简单)** +使用 Docker 部署后端可以避免 Windows 上的依赖问题: +```bash +docker-compose up -d backend +``` + +安装完成后重启后端服务即可正常导出 PDF。 +
+
如何使用 API 中转站? diff --git a/backend/app/services/llm/adapters/litellm_adapter.py b/backend/app/services/llm/adapters/litellm_adapter.py index 880a476..fe4d199 100644 --- a/backend/app/services/llm/adapters/litellm_adapter.py +++ b/backend/app/services/llm/adapters/litellm_adapter.py @@ -105,6 +105,10 @@ class LiteLLMAdapter(BaseLLMAdapter): # 禁用 LiteLLM 的缓存,确保每次都实际调用 API litellm.cache = None + # 禁用 LiteLLM 自动添加的 reasoning_effort 参数 + # 这可以防止模型名称被错误解析为 effort 参数 + litellm.drop_params = True + # 构建消息 messages = [{"role": msg.role, "content": msg.content} for msg in request.messages] diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx index 6301c90..4beeb0e 100644 --- a/frontend/src/pages/Login.tsx +++ b/frontend/src/pages/Login.tsx @@ -59,7 +59,16 @@ export default function Login() { await login(response.data.access_token); toast.success("登录成功"); } catch (error: any) { - toast.error(error.response?.data?.detail || "登录失败,请检查邮箱和密码"); + const detail = error.response?.data?.detail; + // 处理 Pydantic 验证错误(数组格式) + if (Array.isArray(detail)) { + const messages = detail.map((err: any) => err.msg || err.message || JSON.stringify(err)).join('; '); + toast.error(messages || "登录失败"); + } else if (typeof detail === 'object') { + toast.error(detail.msg || detail.message || JSON.stringify(detail)); + } else { + toast.error(detail || "登录失败,请检查邮箱和密码"); + } } finally { setLoading(false); } diff --git a/frontend/src/pages/Register.tsx b/frontend/src/pages/Register.tsx index 612e9ab..ed3639f 100644 --- a/frontend/src/pages/Register.tsx +++ b/frontend/src/pages/Register.tsx @@ -26,7 +26,16 @@ export default function Register() { toast.success('注册成功,请登录'); navigate('/login'); } catch (error: any) { - toast.error(error.response?.data?.detail || '注册失败'); + const detail = error.response?.data?.detail; + // 处理 Pydantic 验证错误(数组格式) + if (Array.isArray(detail)) { + const messages = detail.map((err: any) => err.msg || err.message || JSON.stringify(err)).join('; '); + toast.error(messages || '注册失败'); + } else if (typeof detail === 'object') { + toast.error(detail.msg || detail.message || JSON.stringify(detail)); + } else { + toast.error(detail || '注册失败'); + } } finally { setLoading(false); } diff --git a/frontend/src/shared/api/database.ts b/frontend/src/shared/api/database.ts index 8b12fc1..4562296 100644 --- a/frontend/src/shared/api/database.ts +++ b/frontend/src/shared/api/database.ts @@ -68,6 +68,7 @@ export const api = { const res = await apiClient.post('/projects/', { name: project.name, description: project.description, + source_type: project.source_type || 'repository', repository_url: project.repository_url, repository_type: project.repository_type, default_branch: project.default_branch,