diff --git a/docs/superpowers/demos/2026-09-08-vehicle-cert-batch-zip-demo.html b/docs/superpowers/demos/2026-09-08-vehicle-cert-batch-zip-demo.html new file mode 100644 index 000000000..c77f815b1 --- /dev/null +++ b/docs/superpowers/demos/2026-09-08-vehicle-cert-batch-zip-demo.html @@ -0,0 +1,346 @@ + + + + + + 三方车辆 · 证书附件批量 ZIP 下载 Demo + + + +

三方车辆 · 证书附件批量 ZIP 下载 Demo

+

勾选车辆 → 点「批量下载证书 ZIP」→ 下方展示模拟包结构。单个附件仍可在缩略图右上角单独下载。

+ +
+
+ 承运商 ▾ + 车牌号 + + + + + + + 已选 2 项 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
序号车牌号 + 证书附件 + + 车辆状态
1皖A·D12345 / 挂A8888 +
+
📷↓主·行驶证
+
📷↓挂·行驶证
+
未上传主·道路运输
+
+
正常
2皖B·F67890 +
+
📷↓主·行驶证
+
📷↓主·营运证
+
+
正常
3皖C·H11111—停用
+ +
+
+

+    
+
+ +

入口位置偏好(点击切换上方 Demo 按钮位置):

+
+
+
A
+

工具栏按钮(推荐)

+

勾选后点工具栏「批量下载证书 ZIP」,与导出同级。

+
+
+
B
+

证书附件列头小按钮

+

入口紧贴附件列,语义更近。

+
+
+
C
+

两处都有

+

发现成本最低,略冗余。

+
+
+ +
+
+

勾选 1 辆

+
车辆证书_皖A·D12345.zip
+├── 主·行驶证.jpg
+├── 挂·行驶证.pdf
+└── (无附件证书跳过)
+
+
+

勾选多辆

+
车辆证书批量_2辆_20260908.zip
+├── 皖A·D12345/
+│   ├── 主·行驶证.jpg
+│   └── 挂·行驶证.pdf
+└── 皖B·F67890/
+    ├── 主·行驶证.jpg
+    └── 主·营运证.pdf
+
+
+ + + + diff --git a/docs/superpowers/specs/2026-09-08-vehicle-cert-batch-zip-design.md b/docs/superpowers/specs/2026-09-08-vehicle-cert-batch-zip-design.md new file mode 100644 index 000000000..19d6a5bbd --- /dev/null +++ b/docs/superpowers/specs/2026-09-08-vehicle-cert-batch-zip-design.md @@ -0,0 +1,102 @@ +# 三方车辆 · 证书附件批量 ZIP 下载 + +**日期:** 2026-09-08 +**状态:** 已确认设计,待写实现计划 +**范围:** `web-admin` 三方车辆列表(`/#/pl/base-info/vehicle`) +**实现路径:** 前端 JSZip(不改后端) + +## 背景 + +列表「证书附件」列已支持单个附件下载(`PlCertListAttachmentCell` → `downloadAttachmentFile`)。用户需要:勾选一辆或多辆车后,将该车辆证书附件批量打成 ZIP 下载。 + +## 已确认决策 + +| 项 | 决策 | +|----|------| +| 入口 | 工具栏「批量下载证书 ZIP」(方案 A) | +| 附件范围 | 仅「证书附件」列车辆证书(主车/挂车等),不含照片、不含关联人员证书 | +| 无附件处理 | 跳过无附件车辆;若全部无附件则提示「无可下载附件」 | +| 实现方式 | 前端 JSZip + 现有预签名下载链路(方案 1) | + +## UI 与交互 + +### 入口 + +- 位置:`web-admin/src/views/pl/vehicle/index.vue` 工具栏,靠近「导出」 +- 样式:描边按钮(`btn-ghost`),带 `Download` 图标,文案「批量下载证书 ZIP」 +- 未勾选:按钮禁用 +- 勾选 ≥1:可点;点击后按钮 `loading`,防重复提交 + +### 单文件下载 + +- 列内缩略图右上角 ↓ 保持现状,本期不改 + +### 点击批量下载后 + +1. 从 `selectedRows` 收集证书附件(逻辑对齐列组件:主·/挂·前缀 + `attachmentUrls`) +2. 无附件车辆跳过;全部无附件 → `ElMessage.warning('无可下载附件')`,结束 +3. 有附件 → 拉取文件并打包 → 浏览器下载 ZIP → success 提示 +4. 部分文件失败 → 尽量打出 ZIP,并提示成功数/失败数 + +## ZIP 命名与目录 + +- **有效车辆 1 辆:** `车辆证书_{车牌展示名}.zip`,文件平铺在 ZIP 根目录 +- **有效车辆 ≥2:** `车辆证书批量_{N}辆_{yyyyMMdd}.zip`,每车一个子目录(车牌展示名与列表一致,如含挂车) +- **包内文件名:** 与列 caption 同源(如 `主·行驶证.jpg`);同名冲突追加 `_2`、`_3` +- **目录名安全:** 车牌中的 `/`、`\` 等文件系统不安全字符替换为 `_` + +## 架构与模块 + +仅前端改动,不新增后端接口。 + +| 位置 | 职责 | +|------|------| +| `views/pl/vehicle/index.vue` | 工具栏按钮、勾选校验、调用打包、loading / Message | +| `utils/pl-vehicle-cert-zip.ts`(新建) | 从 `certList` 收集附件、命名、目录结构、JSZip 打包 | +| `utils/download-attachment.ts`(小幅扩展) | 新增「解析预签名 URL 并拉取 Blob」能力(不直接触发 `` 下载) | +| 依赖 | 已有 `jszip`、`file-saver` | + +### 数据流 + +``` +selectedRows + → 解析每行 certList(对齐 PlCertListAttachmentCell) + → 过滤无 URL 的项/车辆 + → 每个文件:fetchAttachmentDownloadUrl → fetch(blob) + → JSZip 写入(单车平铺 / 多车子目录) + → FileSaver.saveAs(zipBlob, filename) +``` + +### 约束 + +- 只用当前列表行已有的 `certList`,不额外请求车辆详情 +- 并发拉取限流(建议同时 3~5 个),避免一次勾选过多打爆浏览器 +- 仅对当前勾选行打包(与现有 table selection 行为一致,含翻页后的 selection 语义) + +## 异常与边界 + +| 场景 | 行为 | +|------|------| +| 未勾选 | 按钮禁用,不弹提示 | +| 勾选但全部无证书附件 | `warning`「无可下载附件」 | +| 部分文件预签名/拉取失败 | 跳过失败项,其余入 ZIP;结束提示成功数/失败数 | +| 全部文件失败 | `error`「下载失败,请稍后重试」,不生成空 ZIP | +| 打包中再次点击 | loading 防重复 | + +## 验收标准 + +1. 勾选 1 辆有附件车辆 → 下载 `车辆证书_{车牌}.zip`,内含该车证书列全部附件 +2. 勾选多辆有附件车辆 → 一个 ZIP,按车牌分子目录 +3. 勾选含「无附件」车辆 → 跳过无附件车,其余正常;全无附件则提示 +4. 列内单个 ↓ 下载行为不变 +5. 不新增后端接口 + +## 非目标(本期不做) + +- 车辆照片、关联人员证书 +- 后端 ZIP / 超大批量流式下载 +- 进度条百分比(仅按钮 loading + 结果 Message) + +## Demo 参考 + +- 交互 Demo:`docs/superpowers/demos/2026-09-08-vehicle-cert-batch-zip-demo.html`