Files

45 lines
3.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: T-588
title: AI工场远程缩略图与蝦皮原图进入照片池
phase: 7
deps: [T-587, T-548]
status: DONE
created: 2026-07-11
---
## 问题 / 背景
拉取商品后要低成本浏览远程主图:缩略图只进内存,用户单击才下载原图落照片池。网络请求不能卡 GUI,失败不能阻断其他缩略图,也不能因为显示缩略图就把全部原图写盘。
## 方案
- 实现异步缩略图 loader(QNetworkAccessManager 或受控线程池+signal),含内存缓存、并发上限、取消、单图重试和占位状态。
- 实探并记录 Shopee CDN 缩略图尺寸后缀、Referer、Content-Type 和重定向事实;不可用时安全回退原 URL 的受限读取。
- 复用现有无系统代理、安全超时、大小上限和图片解码校验;只允许 http/https、公网地址。
- 单击蝦皮原图时下载原图到 `originals/`,先写临时文件并校验解码,再原子替换目标并创建原图 asset;重复单击幂等。
- 明确不增加“导入本地图片”入口;照片池来源仅蝦皮原图和后续 AI 生成图。
## 验收要点
- 缩略图加载不在 GUI 主线程,不落盘;单图失败/超时显示中文状态且其他图继续。
- 缓存命中不重复请求;切项目或关闭窗口可取消未完成加载。
- 单击后原图真实落盘、asset 可用;失败不留下半文件或可用 asset。
- 非图片、超限、内网 URL、坏图片和重定向边界有测试。
- CDN 两项事实有真实探查记录,测试不依赖公网。
## 边界(不改什么)
- 不做 AI 生成、终选、导出或蝦皮写操作。
- 不自动下载全部原图,不加入本地图片导入。
- 不在日志记录 Cookie、带敏感查询串的完整 URL 或图片字节。
## 执行记录
- 2026-07-11:完成 AI工场远程图片底层能力。
- 修正任务依赖:原 `T-546` 任务文件不存在,实际复用已完成的 T-548 图片下载安全/超时口径,frontmatter 改为 `deps: [T-587, T-548]`。
- 新增 `app/image_studio_images.py`:提供远程图片安全下载(http/https、公网地址、无系统代理、连接/读取超时、大小上限、Content-Type 与最终重定向 URL 校验、PIL 解码校验)、内存缩略图生成、线程池 `ThumbnailLoader`(缓存、取消、失败回调)和单张原图下载落 `originals/`。
- `download_original_asset()` 只在用户单击时下载对应原图,写临时文件、解码校验后 `os.replace()` 原子落盘,并通过 `image_studio.update_asset_local_path()` 回写同一 remote asset;重复单击已有可解码本地文件时直接返回,不重复请求。
- 新增 `tests/test_image_studio_images.py` 覆盖缩略图不落盘、缓存命中、取消、原图落盘幂等、坏图片不留下半文件/可用 asset、非图片、超限、内网 URL 和重定向到内网 URL。
- 验证:在只套用 T-588 diff 的 clean worktree 中运行 `python -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`py -3.10 -m unittest discover -s tests`(355 tests)和 `git diff --check`,全部通过。
- CDN 真实实探未执行:本轮没有指定可用的已登录测试账号/商品现场;代码已记录可观测字段 `content_type/final_url/redirected` 并覆盖回退与边界,后续接入 T-591 GUI 前建议用测试账号补一条真实 Shopee CDN 记录。