diff --git a/docs/superpowers/demos/2026-09-23-attachment-image-preview-rotate-demo.html b/docs/superpowers/demos/2026-09-23-attachment-image-preview-rotate-demo.html new file mode 100644 index 000000000..69af6261b --- /dev/null +++ b/docs/superpowers/demos/2026-09-23-attachment-image-preview-rotate-demo.html @@ -0,0 +1,653 @@ + + + + + + 附件图片预览 · 左转 / 右转 Demo + + + + + + +
+
+

附件图片预览 · 旋转 + 缩放

+

对齐 AttachmentUploadField:缩略图点击打开预览弹窗;仅图片显示工具条。

+

交互:左转 / 右转 · 放大 / 缩小 / 重置 · 滚轮缩放 · 拖拽平移 · 关闭后重置。

+

完整可见:缩放倍率 = 1 时,旋转后按外接矩形完整装入预览区;放大后可拖拽查看细节。

+
+ Fresh Mint · #10b981 + 弹窗 860px + 滚轮缩放 + 仅预览态(不写回文件) +
+
+ +
+
+

协议附件(示意)

+

点击下方图片缩略图体验预览旋转;PDF 卡片不可预览旋转。

+
+
+
+ + + 上传附件 +
+ +
+
+ 现场照片-01.jpg +
+ 现场照片-01.jpg +
+ +
+
+ 证件扫描.jpg +
+ 证件扫描.jpg +
+ +
+
+ 📄 + PDF +
+ 协议正文.pdf +
+
+ +
+ 推荐落点:工具条 = 左转 / 右转 · 缩小 / 放大 / 重置; + 预览区滚轮缩放 + 按住拖拽平移。 + 倍率 1 = 完整装入。全部仅预览态,不改 MinIO 原文件。 +
+
+
+ + + + + + diff --git a/docs/superpowers/specs/2026-09-23-attachment-image-preview-rotate-zoom-design.md b/docs/superpowers/specs/2026-09-23-attachment-image-preview-rotate-zoom-design.md new file mode 100644 index 000000000..f1a9fca73 --- /dev/null +++ b/docs/superpowers/specs/2026-09-23-attachment-image-preview-rotate-zoom-design.md @@ -0,0 +1,103 @@ +# 附件图片预览:旋转 / 缩放 / 拖拽(设计) + +日期:2026-09-23 +状态:已确认方案,待实现 +Demo:`docs/superpowers/demos/2026-09-23-attachment-image-preview-rotate-demo.html` + +## 背景 + +`web-admin` 通用附件组件 `AttachmentUploadField`(`web-admin/src/components/business/attachment-upload-field/index.vue`)已支持缩略图卡片与点击预览。图片预览弹窗目前仅静态展示,缺少方向纠正与细节查看能力。 + +用户要求:图片预览打开后支持左转 / 右转;旋转后仍须完整可见(不被预览区裁切);并支持滚轮与按钮缩放、拖拽平移。全部为**仅预览态**,不写回 MinIO / 不改存储 URL。 + +## 目标 + +1. 图片预览弹窗提供工具条:**左转、右转、缩小、放大、重置**。 +2. 预览区内:**鼠标滚轮缩放**、**按住拖拽平移**。 +3. 缩放倍率 = 1 时,任意 0° / 90° / 180° / 270° 下整图按外接矩形完整装入预览区。 +4. 关闭弹窗或点「重置」后,角度 / 缩放 / 偏移归零(重置可保留当前角度或一并归零——本设计约定「重置」= 角度保持、缩放与偏移归零;关闭弹窗则全部归零。与 Demo 一致:重置保留角度)。 +5. 视频、PDF、其它文档预览行为不变。 + +## 非目标 + +- 不把旋转结果写回对象存储或业务附件字段。 +- 不引入第三方图片预览库。 +- 本迭代不强制改造 `BxAttachmentUpload` / `BxAttachmentReadonly`(可后续复用同一交互;若改造成本低可顺带,但不作为门禁)。 +- 不做双指 pinch(桌面管理端为主)。 + +## 方案选择 + +| 方案 | 说明 | 结论 | +|------|------|------| +| A. 增强 `AttachmentUploadField` 现有预览弹窗 | 改动集中,所有使用该组件的页面自动受益 | **采用** | +| B. 抽独立 `ImagePreviewDialog` | 边界更清晰,但需改调用点、范围更大 | 不做 | +| C. 第三方预览库 | 体积与 Fresh Mint / 无 blur 风格对齐成本高 | 不做 | + +## 交互与视觉 + +### 工具条 + +- 位置:预览弹窗 `body` 顶部居中。 +- 按钮(中性描边,对齐 Fresh Mint):左转、右转、缩小、放大、重置。 +- 状态文案:`{角度}° · {缩放百分比}%`(可选,便于调试与用户感知)。 +- 图标:使用 `@element-plus/icons-vue`(如 `RefreshLeft` / `RefreshRight` / `ZoomIn` / `ZoomOut` 或等价),按钮带文案时须有 leading icon(OpenSpec UI 约定)。 + +### 变换模型 + +- 状态:`angle`(度,步进 ±90)、`zoom`(相对「完整装入」的倍率,默认 1)、`offsetX` / `offsetY`(px)。 +- 显示变换:`translate(offset) rotate(angle) scale(fitBase * zoom)`。 +- `fitBase`:按图片自然宽高与预览区可用宽高,计算旋转后外接矩形,取 `min(stageW/boundW, stageH/boundH)`,保证 zoom=1 时完整可见。 +- `zoom` 范围建议:`0.5`~`5`;步进约 `0.15`(滚轮与按钮共用)。 +- zoom ≤ 1 时可将 offset 清零,避免缩小后画面偏出。 +- 窗口 / 弹窗尺寸变化时重新计算 `fitBase` 并应用。 + +### 输入 + +| 输入 | 行为 | +|------|------| +| 左转 / 右转 | angle ±90 | +| 缩小 / 放大 | zoom ± step,夹紧到范围 | +| 重置 | zoom=1,offset=0;**保留**当前 angle | +| 滚轮(预览区) | preventDefault,缩放;不触发页面滚动 | +| 拖拽(预览区) | pointer capture,更新 offset | +| Esc / 关闭 | 关闭弹窗并清空全部预览状态 | +| 键盘(可选增强) | ←/→ 旋转,+/- 缩放,0 等同重置 | + +### 弹窗约束 + +- 保持现有:`append-to-body`、`modal-class="order-module-dialog-mask"`、无 backdrop blur、宽度约 860px。 +- 预览舞台固定高度(如 `min(62vh, …)`),`overflow: hidden`;放大后靠 translate 平移查看,不用滚动条作为主交互。 + +## 实现落点 + +**主文件**:`web-admin/src/components/business/attachment-upload-field/index.vue` + +- 扩展现有 `el-dialog` 图片分支:工具条 + stage 事件。 +- 新增 refs / 计算:`previewAngle`、`previewZoom`、`previewOffset`、`applyPreviewTransform`、`fitBaseScale`。 +- `handlePreviewClosed`:重置全部预览状态。 +- 仅 `isImageFile(previewFile)` 时渲染工具条与交互;其它类型保持现状。 + +**样式**:同文件 scoped SCSS;按钮/stage 对齐 Demo 与 Fresh Mint(主色 `#10b981` 链,中性边框)。 + +**文档(可选)**:OpenSpec `ui-conventions`「附件上传卡片化布局」可补一句「图片预览支持旋转与缩放(仅预览态)」;非实现门禁,可与代码同 PR 或随后补。 + +## 验收标准 + +1. 打开任意图片附件预览:可见左转 / 右转 / 缩小 / 放大 / 重置。 +2. 宽图转 90° 后,在 zoom=100% 时 TOP/BOTTOM 标记(或整图边缘)均在预览区内可见,无裁切。 +3. 滚轮与按钮均可缩放;放大后可拖拽平移。 +4. 关闭再打开:回到 0° · 100% · 无偏移。 +5. PDF / 视频预览无回归;上传 / 下载 / 删除不受影响。 +6. 不发起额外写文件 / 更新附件 URL 的请求。 + +## 风险与注意 + +- `transform` 与 `max-width`/`max-height` 同时使用易导致旋转后裁切;实现须以自然尺寸 + `fitBase * zoom` 为准(与 Demo 一致)。 +- 拖拽与点击关闭遮罩勿冲突:仅在 stage 内拖拽;遮罩点击仍关闭。 +- 滚动穿透:预览区 `wheel` 使用 `{ passive: false }` 并 `preventDefault`。 + +## 参考 + +- Demo:`docs/superpowers/demos/2026-09-23-attachment-image-preview-rotate-demo.html` +- 组件:`web-admin/src/components/business/attachment-upload-field/index.vue` +- UI 规范:`docs/web-admin-ui-spec-fresh-mint.md`;附件布局:OpenSpec `ui-conventions`「附件上传卡片化布局」