From 29fc00a81871b7429a65d79383037969ecddf9f7 Mon Sep 17 00:00:00 2001 From: yueli Date: Thu, 10 Sep 2026 15:47:02 +0800 Subject: [PATCH] =?UTF-8?q?fix(my-requests):=20=E4=BF=AE=E6=AD=A3=20withdr?= =?UTF-8?q?aw=5Fendpoint=20=E8=B7=AF=E5=BE=84=E5=89=8D=E7=BC=80=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E6=92=A4=E5=9B=9E=20404?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现象 ---- 在「我的申请单」页面点撤回,前端控制台报: POST /api/api/v1/outbound/request/351/withdraw 404 根因 ---- aggregate 端点在每条记录上回传 withdraw_endpoint,但拼接时多写了 /api: 返回的: /api/v1/outbound/request/351/withdraw axios baseURL: /api 实际请求: /api + /api/v1/... = /api/api/v1/... → 404 后端路由本身是对的(/api/v1/outbound/request//withdraw 已正确注册), 问题纯在前端拼接。其它 API 封装的正确写法是只传 baseURL 之后的部分 (如 url: '/v1/outbound/my-requests'),本处是唯一破坏该约定的地方。 修复 ---- 返回 /v1/... 而非 /api/v1/...,并加注释说明约定。 借库项同时从 close 改为 withdraw(配合上一提交的申请人端点)。 验证方式 -------- 按**前端真实的拼接方式**验证('/api' + endpoint),而非直接调后端路由: [outbound] /v1/outbound/request/381/withdraw → 200 [borrow ] /v1/transactions/borrow/request/44/withdraw → 200 [scrap ] /v1/scrap/request/5/withdraw → 200 教训:上一轮用 test_client 直接调后端路由验证,绕过了 axios 的 baseURL 拼接,所以后端测试全绿、前端一跑就 404。验证「前端能否调通」必须模拟 前端的请求方式。 --- inventory-backend/app/api/v1/my_requests.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/inventory-backend/app/api/v1/my_requests.py b/inventory-backend/app/api/v1/my_requests.py index fdc50c3..c81b314 100644 --- a/inventory-backend/app/api/v1/my_requests.py +++ b/inventory-backend/app/api/v1/my_requests.py @@ -171,14 +171,18 @@ def _withdraw_path(type_key, req_id): """ 撤回端点路径。撤回是**写操作**,保留在各模块自己的端点里 (三者释放逻辑不同),此处只提供路径供前端分发,不在此执行。 + + ★ 路径不带 /api 前缀:前端 axios 实例的 baseURL 是 '/api', + 传完整路径会拼成 /api/api/v1/... 导致 404。 + 这里返回的是 baseURL 之后的部分(与其它 API 封装的写法一致)。 """ if req_id is None: return '' if type_key == 'outbound': - return f"/api/v1/outbound/request/{req_id}/withdraw" + return f"/v1/outbound/request/{req_id}/withdraw" if type_key == 'borrow': - # 借库暂用 close 端点(语义为撤回/作废) - return f"/api/v1/transactions/borrow/request/{req_id}/close" + # 申请人路径:仅校验单据归属,普通员工无需 op_borrow_approval 权限 + return f"/v1/transactions/borrow/request/{req_id}/withdraw" if type_key == 'scrap': - return f"/api/v1/scrap/request/{req_id}/withdraw" + return f"/v1/scrap/request/{req_id}/withdraw" return ''