diff --git a/app/Note.php b/app/Note.php index 2bc0aef..0f623d0 100644 --- a/app/Note.php +++ b/app/Note.php @@ -298,7 +298,12 @@ final class Note $used = []; foreach (self::blocks($noteId) as $b) { if ((string)$b['kind'] === 'image') { - $used[(string)$b['content']] = true; + // 🔴 工单 #18:content 可能带 `|宽度`,必须剥掉再比; + // 否则"调过宽度的图"排除不掉,会既当图片块又在附件区重复出现。 + $k = self::imageKey((string)$b['content']); + if ($k !== '') { + $used[$k] = true; + } } } $out = []; @@ -452,6 +457,34 @@ final class Note return true; } + /** + * 从图片块的 content 里取出**真正的附件 key**(剥掉 `|宽度` 后缀)。 + * + * 🔴 工单 #18(用户 2026-10-28「笔记功能,上传图片失败」):图片块 content 有两种形态 + * —— `photos/xxx.jpg` 与 `photos/xxx.jpg|50`(前端 `serialize()` 在宽度不是 100 时写后缀)。 + * **凡是拿 content 当 key 用的地方都必须先过这里**,否则带后缀的那个永远匹配不到。 + * + * ⚠️ 曾经的 bug:`claimUploads()` 与 `files()` 直接拿 content 匹配 `attachments.key`, + * 于是"把图片调成 50% 再保存" ⇒ 草稿附件(target_id=0)认领不到 ⇒ 图片变孤儿, + * 用户看到的就是**图片上传失败 / 保存后图没了**。 + * 默认 100% 不写后缀,所以表现为"有时好有时坏",极易被误判成上传问题。 + * + * ⚠️ 修在**服务端**而不是"前端别写后缀":后者会把宽度功能废掉 + * (渲染时要按 content 里的宽度出图,见 templates/notes/form.php 的 $imgParts)。 + * + * @param string $content 图片块 content,形如 `abc` 或 `abc|50` + * @return string 纯 key(可能为空串) + */ + public static function imageKey(string $content): string + { + $c = trim($content); + if ($c === '') { + return ''; + } + $p = explode('|', $c, 2); + return trim($p[0]); + } + /** * 把本次上传的图片块附件从"草稿态"认领到这条笔记上。 * @@ -469,8 +502,12 @@ final class Note { $keys = []; foreach ($blocks as $b) { - if ($b['kind'] === 'image' && $b['content'] !== '') { - $keys[] = $b['content']; + if ($b['kind'] === 'image') { + // 🔴 工单 #18:必须先剥 `|宽度` 后缀,否则带后缀的 key 永远匹配不到 + $k = self::imageKey((string)$b['content']); + if ($k !== '') { + $keys[] = $k; + } } } $db = Database::get();