diff --git a/PROGRESS.md b/PROGRESS.md index 22acc24..efe3285 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -21,6 +21,11 @@ ## 已完成关键能力 +### 2026-06-15 / 文件预览缩放改显式 px:修 CSS zoom 放不大 + +- 接上一条:CSS `zoom` 对带 `max-width/height:100%` 的 flex item 不生效 —— zoom 放大后被百分比 max 约束重新夹回,视觉无变化(用户实测"还是不能放大")。 +- 改法(`web/static/js/preview.js` `_applyZoom`):以 scale=1 的贴合显示尺寸(`clientWidth/Height`)为基准缓存到 `z.baseW/baseH`,缩放时 `max-width/height:none` + 显式 `width/height = base × scale` px;复位时清空还原 CSS 自适应。显式 px 真正撑大布局,body 才出滚动条。bump 0.12.10 → 0.12.11。 + ### 2026-06-15 / 文件预览:修滚动穿透 + 图片 Ctrl+滚轮缩放 - 现象:web 端文件预览弹框内滚滚轮,事件冒泡到背景把对话列表也滚了(scroll chaining);且图片预览无缩放手段。 diff --git a/core/__init__.py b/core/__init__.py index 3ee770e..fac00a8 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -1,3 +1,3 @@ # zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。 # 改版本只动这一行。 -__version__ = "0.12.10" +__version__ = "0.12.11" diff --git a/web/static/js/preview.js b/web/static/js/preview.js index 3248373..ee193da 100644 --- a/web/static/js/preview.js +++ b/web/static/js/preview.js @@ -68,9 +68,28 @@ let _fpCurrentRel = null; const _zoomState = new WeakMap(); // bodyEl -> { img, scale, badge, timer } function _applyZoom(z) { - // 用 CSS zoom(非 transform):zoom 改变布局盒尺寸,放大后 body 才会出滚动条能看溢出部分 - z.img.style.zoom = z.scale === 1 ? "" : z.scale; - z.img.style.cursor = z.scale === 1 ? "zoom-in" : "zoom-out"; + const img = z.img; + if (z.scale === 1) { + // 复位:还原 CSS 里的 max-width/height:100% 自适应贴合 + img.style.maxWidth = ""; + img.style.maxHeight = ""; + img.style.width = ""; + img.style.height = ""; + img.style.cursor = "zoom-in"; + } else { + // 以 scale=1 时的"贴合显示"尺寸为基准,给显式像素尺寸。 + // 不用 CSS zoom:图片是带 max-width/height:100% 的 flex item,zoom 放大后会被 + // 百分比 max 约束重新夹回 → 视觉不变;显式 px + max:none 才真正撑大并让 body 出滚动条。 + if (!z.baseW) { + z.baseW = img.clientWidth || img.naturalWidth; + z.baseH = img.clientHeight || img.naturalHeight; + } + img.style.maxWidth = "none"; + img.style.maxHeight = "none"; + img.style.width = Math.round(z.baseW * z.scale) + "px"; + img.style.height = Math.round(z.baseH * z.scale) + "px"; + img.style.cursor = "zoom-out"; + } z.badge.textContent = Math.round(z.scale * 100) + "%"; z.badge.classList.add("show"); if (z.timer) clearTimeout(z.timer); @@ -84,7 +103,7 @@ function _makeImageZoomable(bodyEl, img) { const badge = document.createElement("div"); badge.className = "zoom-badge"; // 挂到 card 而非 body,放大后 body 滚动时徽标不跟着滚走 card.appendChild(badge); - const z = { img, scale: 1, badge, timer: null }; + const z = { img, scale: 1, badge, timer: null, baseW: 0, baseH: 0 }; _zoomState.set(bodyEl, z); img.style.cursor = "zoom-in"; img.addEventListener("dblclick", () => { z.scale = 1; _applyZoom(z); });