feat(gallery): 原图查看与下载——仓外 originals store 双轨制
- git 仓只进压缩版(构建用);原图落 ~/docker_apps/blog/photos-originals/
(迁移器/ingest 双入口写入,幂等),build.sh 独立 rsync 到
staging/photos-originals/(同一静态根,零 nginx 改动)
- lightbox 增「原图」(新标签全尺寸)+「下载」(download 属性带文件名)
- 原图持久保障:store + Phase 0 备份 tar 双留档;存量 21 张已回填(196M)
验证: astro build 11 页 exit 0;dist/gallery 含 lb-original×2 与
photos-originals 引用;staging/photos-originals 21 张实测
Spec: none (用户功能补req:原图查看/下载,跨 Phase 独立小特性)
Co-authored-by: GLM-5.3
This commit is contained in:
1 parent
382e56431f
commit
44bfb23efb
4 files changed
+50
-4
No files matched your search
@@ -47,6 +47,8 @@ const cards = await Promise.all(
|
||||
image: photo.data.image,
|
||||
exif: formatExif(photo.data.exif),
|
||||
fullSrc: full.src,
|
||||
// 原图走仓外 store(构建时独立 rsync 到 /photos-originals/),git 不背 196M
|
||||
original: `/photos-originals/${photo.id}.jpg`,
|
||||
w,
|
||||
h,
|
||||
s3: spanFor(w, h, 3),
|
||||
@@ -84,6 +86,7 @@ const first = cards[0];
|
||||
data-title={card.title}
|
||||
data-exif={card.exif}
|
||||
data-full={card.fullSrc}
|
||||
data-original={card.original}
|
||||
aria-label={`查看大图:${card.title}${card.exif ? `(${card.exif})` : ''}`}
|
||||
>
|
||||
<Image
|
||||
@@ -119,6 +122,10 @@ const first = cards[0];
|
||||
<div class="lb-meta">
|
||||
<strong id="lb-title">{first?.title}</strong>
|
||||
<span id="lb-exif">{first?.exif}</span>
|
||||
<span class="lb-orig">
|
||||
<a id="lb-original" href={first?.original} target="_blank" rel="noopener">原图</a>
|
||||
<a id="lb-download" href={first?.original} download>下载</a>
|
||||
</span>
|
||||
</div>
|
||||
<button id="lb-next" class="tap lbnav" type="button" aria-label="下一张(→)">
|
||||
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
@@ -150,6 +157,11 @@ const first = cards[0];
|
||||
img.alt = btn.ariaLabel ?? '';
|
||||
titleEl.textContent = btn.dataset.title ?? '';
|
||||
exifEl.textContent = btn.dataset.exif ?? '';
|
||||
const orig = btn.dataset.original ?? '';
|
||||
(document.getElementById('lb-original') as HTMLAnchorElement).href = orig;
|
||||
const dl = document.getElementById('lb-download') as HTMLAnchorElement;
|
||||
dl.href = orig;
|
||||
dl.setAttribute('download', btn.dataset.title ?? 'photo');
|
||||
if (!reduced.matches) {
|
||||
img.style.opacity = '0';
|
||||
requestAnimationFrame(() => {
|
||||
@@ -315,6 +327,18 @@ const first = cards[0];
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12.5px;
|
||||
}
|
||||
.lb-orig {
|
||||
display: inline-flex;
|
||||
gap: var(--space-3);
|
||||
margin-left: var(--space-2);
|
||||
}
|
||||
.lb-orig a {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
color: var(--accent);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 0.2em;
|
||||
}
|
||||
.lb-meta {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
@@ -352,6 +376,18 @@ const first = cards[0];
|
||||
}
|
||||
@media (max-width: 560px) {
|
||||
.lb-bottom { flex-wrap: wrap; }
|
||||
.lb-meta { order: 3; flex-basis: 100%; }
|
||||
.lb-orig {
|
||||
display: inline-flex;
|
||||
gap: var(--space-3);
|
||||
margin-left: var(--space-2);
|
||||
}
|
||||
.lb-orig a {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
color: var(--accent);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 0.2em;
|
||||
}
|
||||
.lb-meta { order: 3; flex-basis: 100%; }
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user