diff --git a/PROGRESS.md b/PROGRESS.md
index 2160f9b..3ada729 100644
--- a/PROGRESS.md
+++ b/PROGRESS.md
@@ -2,7 +2,7 @@
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`。
-最后更新:2026-06-29(ppt skill 重构为 SVG-first,移植 ppt-master + bump 0.33.0)
+最后更新:2026-06-30(web 端 SVG 预览修复:强制 image/svg+xml + bump 0.33.1)
---
@@ -21,6 +21,9 @@
## 已完成关键能力
+### 2026-06-30 / 修复 web 端 SVG 无法预览(bump 0.33.1)
+SVG 在 `
` 里必须 Content-Type=`image/svg+xml` 才渲染。前端 `preview.js` 的 `_showImage` / mini 图片分支据扩展名强制 blob mime(与服务端响应头无关);后端 `download` 接口对 `.svg` 显式回 `image/svg+xml`(部分部署环境 mimetypes 未注册 svg → 会被 FileResponse 猜成 octet-stream)。双保险。
+
### 2026-06-29 / ppt skill 清空重构为 SVG-first(移植 ppt-master,bump 0.33.0)
- 背景:旧 ppt skill 用 python-pptx + 固定组合版式件(`add_card_grid` 等),版面被 helper 框死 → 单调、AI 味重,是架构天花板,调参救不了。用户要求"清空重做,参考 github ppt-master"。
diff --git a/core/__init__.py b/core/__init__.py
index 23f8987..ca29ba6 100644
--- a/core/__init__.py
+++ b/core/__init__.py
@@ -1,3 +1,3 @@
# zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。
# 改版本只动这一行。
-__version__ = "0.33.0"
+__version__ = "0.33.1"
diff --git a/web/app.py b/web/app.py
index ad58e7d..55d4e86 100644
--- a/web/app.py
+++ b/web/app.py
@@ -2755,9 +2755,15 @@ def create_app() -> FastAPI:
# workspace 文件可变, 禁浏览器启发式缓存 (RFC 7234 默认能缓数小时)
# 否则文件改了 SPA 预览还是旧内容
# (Starlette FileResponse 不实现 304, 总是 200 全量; workspace 文件小, 可接受)
+ # .svg 显式给 image/svg+xml: 部分部署环境 mimetypes 未注册 svg, FileResponse
+ # 会猜成 octet-stream, 前端
就渲染不出 SVG 预览
+ media_type = None
+ if target.suffix.lower() == ".svg":
+ media_type = "image/svg+xml"
return FileResponse(
path=str(target),
filename=target.name,
+ media_type=media_type,
headers={"Cache-Control": "no-cache"},
)
diff --git a/web/static/js/preview.js b/web/static/js/preview.js
index fe5bef9..5ba9455 100644
--- a/web/static/js/preview.js
+++ b/web/static/js/preview.js
@@ -228,7 +228,11 @@ export async function openFilePreview(rel) {
}
function _showImage(blob) {
- const url = _trackBlobUrl(blob);
+ // SVG 在
里必须 Content-Type=image/svg+xml 才渲染;下载接口靠服务端
+ // mimetypes 猜类型,部分部署环境(Linux)未注册 .svg → octet-stream → 不显示。
+ // 这里据扩展名强制纠正,与服务端响应头无关。
+ const mime = /\.svg$/i.test(_fpCurrentRel || "") ? "image/svg+xml" : "";
+ const url = _trackBlobUrl(blob, mime);
const body = $("fp-body");
body.className = "body center";
body.innerHTML = "";
@@ -470,7 +474,8 @@ async function openMiniFilePreview(rel) {
body.className = "body center";
const img = document.createElement("img");
img.className = "preview-img";
- img.src = _trackMiniBlobUrl(blob);
+ const _mime = /\.svg$/i.test(_mpCurrentRel || "") ? "image/svg+xml" : "";
+ img.src = _trackMiniBlobUrl(blob, _mime);
body.appendChild(img);
_makeImageZoomable(body, img);
} else if (cat === "video") {