diff --git a/changelogs-v2/2026-06/12_前端Bug_车辆批量导入responseType-blob致成功误报失败-管理后台.md b/changelogs-v2/2026-06/12_前端Bug_车辆批量导入responseType-blob致成功误报失败-管理后台.md new file mode 100644 index 0000000..1f24169 --- /dev/null +++ b/changelogs-v2/2026-06/12_前端Bug_车辆批量导入responseType-blob致成功误报失败-管理后台.md @@ -0,0 +1,56 @@ +# 【前端 Bug·管理后台】车辆批量导入:后端成功但前端误报「导入失败」(responseType=blob 读 responseText 抛错) + +> 页面:车务管理 → 车辆档案 → 车辆列表 → 批量导入 | 接口:`POST /admin/fleet/vehicles/import` | 负责:mmg +> 严重度:P1(功能可用但误导用户重复导入,撞车牌唯一约束/重复绑常驻) + +## 现象 + +用户用最新模板(12 列,含常驻司机手机号)批量导入 5 台车,前端弹「导入失败」,但**实际后端已全部成功**: + +- DevTools Network 里 `import` 请求 Response:`code:200, insertedCount:5, errorCount:0, success:true` +- 车辆列表 `共 16 辆` → `共 21 辆`(+5),5 台车 + 常驻司机绑定全部落库正确 +- Console 报错:`InvalidStateError: Failed to read the 'responseText' property from 'XMLHttpRequest'. The value is only accessible if the object's 'responseType' is '' or 'text' (was 'blob').` + +## 根因(纯前端) + +导入按钮的 XHR/axios 请求把 `responseType` 设成了 `'blob'`——几乎可以确定是从**同页「下载模板」按钮**的代码复制来的(下载模板返回 .xlsx 文件流,确实需要 `responseType:'blob'`)。但**导入接口返回的是 JSON**(`Content-Type: application/json`,`Result` 包络),前端拿到响应后去读 `responseText` 解析 JSON,而浏览器规定 `responseType` 为 `'blob'` 时禁止访问 `responseText` → 抛 `InvalidStateError` → 被 catch 当成请求失败 → 弹「导入失败」。 + +→ HTTP 其实是 200、业务也成功,**纯前端响应解析配置错误**,与后端无关。 + +## 后端契约(未变,供前端对照) + +| 端点 | 方法 | 响应类型 | responseType 应设 | +|---|---|---|---| +| `/admin/fleet/vehicles/import` | POST(multipart 上传文件) | **JSON**(`Result`) | `''` 或 `'json'`(**不要 blob**) | +| `/admin/fleet/vehicles/import/template` | GET(下载模板) | **二进制 .xlsx 文件流**(`Content-Disposition` 附件) | `'blob'`(保持) | + +导入成功响应示例(前端应据此渲染导入结果弹窗): + +```json +{ + "code": 200, + "message": "成功", + "data": { + "totalRows": 5, + "insertedCount": 5, + "updatedCount": 0, + "errorCount": 0, + "errors": [], + "warnedCount": 0, + "warnings": [] + }, + "success": true +} +``` + +部分失败时 `errors[]` 含 `{row, plate, msg}`、`warnings[]` 含 `{row, plate, field, msg}`,建议前端按这两个数组渲染「成功 N 条 / 失败 M 条(逐行原因)/ 警告 K 条」明细,而不是只弹一句成功或失败。 + +## 修复建议(前端) + +1. **导入请求单独配置**:导入用默认 `responseType`(`''`/`'json'`),不要复用下载模板的 `blob` 配置——两个按钮的 axios 调用分开写。 +2. **成功判定改看业务结果**:以 `data.errorCount`/`data.errors` 渲染明细,别只凭「请求是否抛异常」判断成败。 +3. 回归:导入成功(全成)、部分失败(含 errors)、全失败 三种响应都要能正确解析渲染。 + +## 临时说明(给已踩坑的同学) + +看到「导入失败」请先刷新车辆列表确认是否其实已导入——若已在列表里,说明是本 Bug,**不要重复导入**(重复上传同车牌会走 UPDATE 不会重复建,但若手动改了车牌重传会造成重复车 + 常驻司机 1:1 冲突报错)。