- GET /api/library/media/usage: read-only occupancy report per file —
every live canvas card with canvas title, project/session scope, and
the real consequence of deleting that card (deletes_file / keep reason)
- _path_on_canvas joins canvas: orphan nodes (canvas row gone, FK-cascade
dead metadata) no longer count as occupancy; they are reported as
invalid references with totals instead of blocking deletion
- canvas deleteNode: keep_file=true release-only variant (card removed,
file always preserved); artifact cards with a live pending/running job
refuse deletion (409) so completion events cannot resurrect them
- library UI: occupancy modal on kept(on_canvas) with locate / delete
card (accurate impact text) / release-only actions, per-path free-file
delete closing the loop, invalid-reference note, offset paging for
large counts, library selection persisted across canvas round-trips
- canvas UI: ?locate=<node> deep-link centers the card (computed
viewport, no store.fitView — its nodes write-back looped the graph
rebuild effect), gold ring highlight + dismiss, back-to-library chip
- i18n keys for all 7 languages; e2e runner + 32-check real-browser
regression on isolated data
Co-authored-by: multica-agent <github@multica.ai>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
闭环
知道在哪 → 直接定位 → 明确处理占用 → 确能完成删除。
变更
后端
GET /api/library/media/usage?path=&offset=(只读):逐条列出仍在使用该文件的画布卡片——画布可读名/ID、卡片标题/ID、所属项目或会话上下文、生成中状态、以及删除该卡片的真实后果(deleting_card_deletes_file+ 否则给出file_keep_reason)。纯 SQL 直读,不 seed 实体、不物化产物。引用多时分页(每页 50,带valid_total)。_path_on_canvasJOIN canvas——canvas 行已不存在的节点(FK 级联契约下的死元数据,任何入口不可达)不再计入占用、不再挡删除;usage 接口将其单列为invalid(带总数、无链接、不静默清除)。线上历史孤儿数据是否清理单独报总管,不随部署批清。DELETE /api/canvas/{id}/nodes/{id}?keep_file=true:独立、最小、原文件保全的"仅解除引用"操作。默认行为不变(最后一份引用且在素材库范围内时连文件一起删——UI 如实告知,不包装成无损)。前端
/canvas/{id}?locate={node_id},卡片居中(按图数据+实测卡片盒直接算 viewport 写回——store.fitView 的 nodes 回写会与图重建 effect 成环)+ 金色高亮环 20s + "返回素材库"胶囊;后退回素材库保持原选择(sessionStorage 持久化)。自测
test_library_usage.py(跨画布多引用/孤儿不再占用且如实上报/只读不 seed/反斜杠路径/生成中标记/分页顺序/参数校验)+test_canvas_delete.py扩展(keep_file 原文件保全并回到可删、生成中 409→done 放行、jobs 权威覆盖陈旧状态、孤儿不算引用);全套 1077 过 / 8 失败均为 base 既有(同 base 实核),Ruff 通过。e2e/run-hel884.py+e2e/hel884.cjs,隔离库+自建媒体+真实浏览器,32 项全过):孤儿直接可删、占用弹层双引用齐全、定位到正确画布正确卡片且视口外卡居中、返回保持选择、删一卡另一卡保留文件、最后引用随卡删文件、仅移除保全文件后弹层内完成删除、生成中无操作入口、取消不变、刷新后列表与画布均不复活。全程未调真实 LLM/GPU/收费服务;未触碰线上数据。边界
不合并部署;线上历史孤儿数据不动(如需修数据另报);项目引用与别处有效引用保护保持;路径比较沿用既有分隔符规范化,未放宽边界/权限。