admin- 设计并开发图片生命周期管理子系统

记录一下这一个月开发的编辑器之子系统

设计并实现了一套图片生命周期管理子系统,包含:
本地 + 远程双重去重、blob 资源自动回收、批量上传调度(带实时进度与并发控制)、异步上传期间仍可安全编辑(草稿级原子性保证)、以及带吸附机制的裁剪器(兼顾用户体验和去重稳定性)。

1. 去重:同一张图,只认一份

  • 本地去重(session 级)

    • 同一轮编辑里,用户反复选择同一文件,不会重复算 hash、重复上传。

    • 依靠本地的 sha 记录 + id 映射,避免 CPU 和带宽浪费。

  • 远程去重(存储级)

    • 同一原图 + 同一裁剪尺寸,只会在 R2 里存一份。

    • 其他场景直接复用 storageKey,既省钱又省时间。

不论你在多少页面、多少草稿里折腾同一张图,存储端只算一份账


2. 资源管理:用完就丢,浏览器不会越用越卡

  • 所有通过 URL.createObjectURL 产生的临时 blob: 链接,在不再需要时都会被统一 URL.revokeObjectURL

  • 结合 per-draft 的 ids 收集函数,可以做到「某个草稿的临时图,全量清场」。

这让裁剪器在频繁换图、多次尝试的场景下,内存不会慢慢膨胀变成 Chrome 杀手


3. 上传管线:聚合、进度、并发,一套齐活

  • 任务聚合:多张图片会被打包进统一的上传流程,而不是一个个发散请求。

  • 实时进度条:不仅有“共 N 张图已上传 M 张”,还有字节级别的 loadedBytes / totalBytes

  • 并发控制:内部已经支持限制并发数,防止把用户网络打爆(只是现在 UI 没给开关)。

写了一个小型的「上传调度器」,而不仅是 Promise.all(fetch(...)) 那种简单粗暴。


4. 异步上传 + 可继续编辑,但保证原子性

  • 上传是完全 异步 的:用户点了 Apply crop 之后,不需要傻等,可以继续在别的字段/别的图片上编辑。

  • 同时,通过草稿层的 patch + 状态机设计,保证:

    • 要么这批涉及到的图片 + draft 更新整体成功;

    • 要么失败时不会出现“部分字段写成新图、部分字段还是旧图”的脏状态。

体验上就是:你可以一边改图一边写文案,保存那一刻整个草稿是自洽的


5. 裁剪交互:「吸附」让像素级差异不再是噩梦

  • 在缩放 / 拖拽时,如果当前姿态「非常接近」默认姿态,会自动吸附回默认点:

    • scale / tx / ty 都会 snap 到 defaultPose;

    • 同时把 didInteractRef 置回 false

  • 这背后有两个意义:

    1. 体验:用户不用为了“完全回到初始”像素级调滑块,有点偏差就自动帮你校正。

    2. 工程:这让去重变得可行

      • 否则你会遇到那种:“明明肉眼看完全一样,但因为差了 0.0001 像素导致 params 不同” → hash/去重全部失效。

等于给交互层加了一个「人类容错层」,帮用户对齐系统的判断标准。

posted @ 2025-11-16 07:14  PEAR2020  阅读(8)  评论(0)    收藏  举报