From c242bfb12c3ad088916e030b4a3b400a4b575233 Mon Sep 17 00:00:00 2001 From: mole404 <248403041+mole404@users.noreply.github.com> Date: Fri, 2 Oct 2026 14:59:40 +0800 Subject: [PATCH] =?UTF-8?q?fix(tags):=20=E4=BB=A3=E7=A0=81=E5=AE=A1?= =?UTF-8?q?=E6=9F=A5=E5=8F=91=E7=8E=B0=E7=9A=84=206=20=E6=9D=A1=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E5=85=A8=E4=BF=AE=20+=20=E8=A1=A5=E7=9C=9F=E6=9C=BA/?= =?UTF-8?q?=E9=9D=99=E6=80=81=E6=96=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 审查(含新加的打标部分)发现并修掉: 1. 改名/删除标签会清空选中 ✗ —— refreshAfterTagChange() 走 setTags() → resetImages(), 会清空图片墙并 ds.clearSelection(),把用户正在打标的这批图连同弹窗勾选态一起丢掉 (老师问过的「编辑/删除会整页刷新」)。改为 patchCardsTag() 就地同步(卡片角标 + data-json + 详情卡 chip);只有「被删的标签正用作筛选项」这种结果集真的变了的情况才调 setTags()。 2. 删图片/删用户不清 image_tag / tags ✗ —— 两个迁移的注释都写着「关联行由应用代码显式删除」, 图片这条路径没落实,残留行会无声累积。UserService::deleteImages() 补 detach(); 后台删用户时一并清标签与关联行。(本机 SQLite 未启用 PRAGMA foreign_keys,不能指望级联。) 附带 tools/check-tag-integrity.php:只读自检残留行,退出码非 0 即为异常。 3. 标签名进 data-json(单引号属性)未转义 ✗ —— 名字里带 ' 就能提前闭合属性(自伤型 XSS 面)。 三处注入(列表渲染 / 弹窗行 / syncCardTags)统一先 escapeHtml 再写。 4. 弹窗里几个 axios 调用没有 catch ✗ —— 网络错误或 422(名字超 64 字)会静默无反应。 统一走 apiErrMsg() 取后端 message;三个标签名输入框补 maxlength=64。 5. 后端 trim() 在校验之后 ✗ —— 只输入空格会建出空名标签。TagRequest 加 prepareForValidation()。 6. 两处硬编码路径 ✗(action="/user/tags/__id__"、axios.delete('/user/tags/'+id))→ 改用 route()。 测试: - jsdom 118/118(新增 7 条:改名的局部同步、data-json 转义、maxlength+catch、 deleteImages/删用户的清理、TagRequest trim;测试台补 renderTagRoutes 渲染带 id 的路由)。 - 真机 70/70(新增 #2c:改标签名后选中不丢 / 图片墙不重载 / 角标就地换名, 6 项断言,在整轮末尾单开 context 跑,避免本机 1vCPU/965MB 下的页面 OOM)。 - 真机实证:图片挂 1 条关联 → deleteImages → 残留 0;check-tag-integrity.php 干净 ✓。 - tools/diff-vs-upstream.sh:已知偏离清单补登 UserService.php / Admin\UserController.php, 校验通过(103 项,恰好等于实际偏差)。 - patches/ios-longpress.patch 按原范围(3 个文件)重新生成。 --- Dockerfile | 4 +- patches/ios-longpress.patch | 456 +++++++++++++----- .../Http/Controllers/Admin/UserController.php | 4 + src/app/Http/Requests/TagRequest.php | 14 + src/app/Services/UserService.php | 4 + src/resources/views/user/images.blade.php | 95 +++- test/tag-feature.test.mjs | 49 +- tools/check-tag-integrity.php | 39 ++ tools/diff-vs-upstream.sh | 7 + 9 files changed, 516 insertions(+), 156 deletions(-) create mode 100644 tools/check-tag-integrity.php diff --git a/Dockerfile b/Dockerfile index ae96cd1..ff47455 100644 --- a/Dockerfile +++ b/Dockerfile @@ -165,7 +165,7 @@ RUN php -r "file_exists('.env') || copy('.env.example', '.env');" \ RUN printf '%s\n' \ 'c0e513ec8e93fd81b34b3c6de5cf5eb8 ./public/js/context-js/context-js.js' \ 'c0e513ec8e93fd81b34b3c6de5cf5eb8 ./resources/js/context-js.js' \ - '1292ea8123868897023def9dc9bcf5ac ./resources/views/user/images.blade.php' \ + '23835058801c2b609c2134f0f10d0a5d ./resources/views/user/images.blade.php' \ | md5sum -c - \ && grep -q "assetVersion('js/context-js/context-js.js')" ./resources/views/user/images.blade.php \ && grep -q 'isIOSWebKit' ./public/js/context-js/context-js.js \ @@ -208,7 +208,7 @@ RUN APP_SRC_MD5=$(find app config routes -type f -print0 2>/dev/null | sort -z | "fork_sha=${FORK_SHA}" \ "lsky_commit=${LSKY_COMMIT}" \ "context_js_md5=c0e513ec8e93fd81b34b3c6de5cf5eb8" \ - "images_blade_md5=1292ea8123868897023def9dc9bcf5ac" \ + "images_blade_md5=23835058801c2b609c2134f0f10d0a5d" \ "app_src_md5=${APP_SRC_MD5}" \ "app_js_md5=${APP_JS_MD5}" \ "app_css_md5=${APP_CSS_MD5}" \ diff --git a/patches/ios-longpress.patch b/patches/ios-longpress.patch index aee2ea0..e06da16 100644 --- a/patches/ios-longpress.patch +++ b/patches/ios-longpress.patch @@ -52,7 +52,7 @@ # 三个文件各自的 md5(与 Dockerfile「自证 2」里的期望值一致): # c0e513ec8e93fd81b34b3c6de5cf5eb8 src/resources/js/context-js.js # c0e513ec8e93fd81b34b3c6de5cf5eb8 src/public/js/context-js/context-js.js -# 1292ea8123868897023def9dc9bcf5ac src/resources/views/user/images.blade.php +# 23835058801c2b609c2134f0f10d0a5d src/resources/views/user/images.blade.php # # 上游原文件 md5(改动前,供比对): # c8e57f6232848ca8277341ddf1a3a7a6 resources/js/context-js.js @@ -62,8 +62,9 @@ # 2026-10-01 第二轮(老师试完测试版提的意见):两个标签窗口合并成一个(旧 tag-manage-modal 删除)、 # 三态勾选改成两态、加「显示图片标签」开关、修好卡片拖动框选(图片穿透 + 拖动起点放宽 + # 由卡片自己开预览)。 ---- a/resources/js/context-js.js -+++ b/resources/js/context-js.js +---- src/resources/js/context-js.js +--- /root/.hermes/cache/scratch/tmp.BQ92ALlEpf/up/resources/js/context-js.js 2026-10-02 14:31:26.703747972 +0800 ++++ src/resources/js/context-js.js 2026-10-01 15:40:13.406864745 +0800 @@ -2,9 +2,49 @@ * Context.js * Copyright Jacob Kelley, Modified by WispX @@ -1147,8 +1148,9 @@ + + return api; })(); ---- a/public/js/context-js/context-js.js -+++ b/public/js/context-js/context-js.js +---- src/public/js/context-js/context-js.js +--- /root/.hermes/cache/scratch/tmp.BQ92ALlEpf/up/public/js/context-js/context-js.js 2026-10-02 14:31:26.695747977 +0800 ++++ src/public/js/context-js/context-js.js 2026-10-02 12:22:32.584186106 +0800 @@ -1 +1,1148 @@ -window.context=window.context||function(){let e={fadeSpeed:100,filter:function(e){},above:"auto",preventDoubleContext:!0,compress:!1};function t(o,n,d,i){let a=i?" dropdown-context-sub":"",s=e.compress?" compressed-context":"",f=$('
'),l=0,r="";for(;l标签管理
+__hint__
-+ ++ {{-- 新建标签放在首行(老师要求):进窗口第一眼就能建新标签 --}} +