diff --git a/public/admin/config.yml b/public/admin/config.yml index bc1cdf1..2f2b4e3 100644 --- a/public/admin/config.yml +++ b/public/admin/config.yml @@ -132,7 +132,7 @@ collections: # title 必填:Astro schema z.string() 无 .optional(),omit 纪律下必需且有值才会落键(空 title 会让 main 不可构建) - { label: 标题, name: title, widget: string, required: true } - { label: 图片, name: image, widget: image } - - { label: 分组, name: group, widget: select, options: [street, landscape] } + - { label: 分组, name: group, widget: string, hint: '小写英文短词(如 landscape / street / portrait);新分组直接输入新词,图库筛选会自动出现' } - { label: 替代文本, name: alt, widget: string, required: false } - { label: 人为描述, name: caption, widget: text, required: false, hint: 展示在灯箱里的人为描述(一句话策展文案) } - label: EXIF 覆盖(一般留空,构建期自动从图提取) diff --git a/public/admin/index.html b/public/admin/index.html index 029ba68..7d250bc 100644 --- a/public/admin/index.html +++ b/public/admin/index.html @@ -9,23 +9,53 @@ + /* 速通坞(5n D1 + 用户实测防误触改版):默认收起成一枚小圆钮, + 点开才展开五入口;开关状态存 localStorage(手机端默认必收起)。 + 收起态只有一个 26px 圆钮,不再与编辑区抢点击面。 */ + #qd-toggle{position:fixed;top:10px;right:12px;z-index:9000;width:26px;height:26px; + border-radius:50%;border:1px solid rgba(127,131,140,.4);background:rgba(255,255,255,.85); + color:#5b6472;font:14px/1 system-ui,sans-serif;cursor:pointer;opacity:.6;transition:opacity .2s} + #qd-toggle:hover{opacity:1} + body[data-qd=open] #qd-toggle{background:rgba(52,84,209,.12);color:#3454d1;border-color:rgba(52,84,209,.4)} + #qd-links{position:fixed;top:44px;right:12px;z-index:9000;display:none;flex-direction:column;gap:4px; + font:12px/1 system-ui,sans-serif;padding:6px;border-radius:10px;background:rgba(255,255,255,.95); + box-shadow:0 2px 10px rgba(0,0,0,.12)} + body[data-qd=open] #qd-links{display:flex} + #qd-links a{color:#5b6472;text-decoration:none;padding:5px 10px;border-radius:6px;white-space:nowrap} + #qd-links a:hover{color:#3454d1;background:rgba(52,84,209,.08)} + + diff --git a/src/components/pages/GalleryPage.astro b/src/components/pages/GalleryPage.astro index da37171..d1ff04e 100644 --- a/src/components/pages/GalleryPage.astro +++ b/src/components/pages/GalleryPage.astro @@ -73,6 +73,14 @@ const cards = await Promise.all( }), ); const first = cards[0]; +// 分组筛选动态化(5n 后续):后台分组已开放自由输入(select 无 creatable), +// 这里从数据反向派生筛选片——新分组零配置自动出现。 +// 仅 [a-z0-9-] 命名的分组生成 CSS 规则(选择器安全);其余分组仍正常展示在「全部」里 +const groups = [...new Set(cards.map((c) => c.group).filter(Boolean))] + .filter((g) => /^[a-z0-9-]+$/.test(g)); +const filterRules = groups + .map((g) => `.g-main:has(#f-g-${g}:checked) .shot:not([data-group='${g}']) { display: none; }`) + .join('\n'); --- @@ -82,10 +90,12 @@ const first = cards[0]; {t('gallery_filter_legend', locale)} - - - - + {groups.map((g) => ( + + + + + ))}
@@ -618,8 +628,7 @@ const first = cards[0]; .chip:hover { color: var(--ink-1); border-color: var(--ink-4); } .f-input:focus-visible + .chip { outline: 2px solid var(--accent); outline-offset: 2px; } .f-input:checked + .chip { color: var(--ink-1); border-color: var(--ink-3); font-weight: 500; } - .g-main:has(#f-street:checked) .shot:not([data-group='street']) { display: none; } - .g-main:has(#f-landscape:checked) .shot:not([data-group='landscape']) { display: none; } + /* 动态分组筛选规则见下方 is:global 块(分组来自数据,构建期生成) */ /* masonry:stage 是容器查询锚,行高/列距以 stage 宽为基(cqw) */ .stage { container-type: inline-size; } @@ -1035,4 +1044,5 @@ const first = cards[0]; border-radius: 6px; } .shot img, .thumb img { border-radius: var(--radius-img); } + diff --git a/tests/e2e.mjs b/tests/e2e.mjs index 9211084..f4b873a 100644 --- a/tests/e2e.mjs +++ b/tests/e2e.mjs @@ -295,14 +295,12 @@ await page.keyboard.press('Escape'); ok('灯箱·Esc 关闭', await page.locator('#lb[open]').count() === 0); // 7) 分组筛选(当前库存单组:21 张全 landscape;验证筛选逻辑用街拍=0 反证) -await page.click('label[for=f-landscape]'); +await page.click('label[for=f-g-landscape]'); // 5n:分组筛选动态化(数据派生 id) await page.waitForTimeout(200); const landscapeShown = await page.locator('.shot:visible').count(); ok('图库·风景筛选', landscapeShown === 21, `${landscapeShown} 张`); -await page.click('label[for=f-street]'); -await page.waitForTimeout(200); -const streetShown = await page.locator('.shot:visible').count(); -ok('图库·街拍筛选(应为0)', streetShown === 0, `${streetShown} 张`); +// 5n:分组筛选动态化——筛选片由数据派生(当前库存仅 landscape 一组,不再有 street 档) +ok('图库·筛选片数据派生', (await page.locator('.filters .chip').count()) === 2); await page.click('label[for=f-all]'); // 8) 书评字体(思源宋)与技术页 TOC