图片预览手机适配 + 正文图统一接入 lightbox

- lightbox:打开锁背景滚动(手机上背景不再跟着滑)、手机滑动左右翻页、
  dvh 跟随全面屏可视高度、关闭钮/角标走 safe-area、图片全宽无圆角
- 全局 capture 委托:时间线/详情页 v-html 正文里的图统一可点开预览,
  capture+stop 压住整卡跳转;thumbifyHtml 把原图地址留在 data-fullsrc,
  预览用原图而非 480w 缩略图;链接卡缩略图不劫持(点击仍是打开链接)
This commit is contained in:
Sakurasan
2026-09-29 01:29:19 +08:00
parent c2d5e9db89
commit ce07f4a347
3 changed files with 87 additions and 16 deletions
+25 -2
View File
@@ -7,9 +7,26 @@ import ImgLightbox from './components/ImgLightbox.vue'
import YohakuTop from './ui/yohaku/YohakuTop.vue'
import YohakuFoot from './ui/yohaku/YohakuFoot.vue'
import { site, setAdminScope } from './site'
import { openLightbox } from './lightbox'
const route = useRoute()
// 正文图片点击预览(capture 阶段):时间线/详情页里 v-html 的正文图
// 都没有自己的点击入口,这里统一接管。capture + stopPropagation 是为了
// 压住整卡点击(时间线点图不该跳详情);配图网格有自己的 handler 不在
// .prose 内,天然不受影响。lightbox 用 data-fullsrc 原图(thumbify 保留)。
function onProseImgClick(e) {
const img = e.target
if (!img || img.tagName !== 'IMG') return
const scope = img.closest('.prose')
if (!scope || img.closest('.post-imgs') || img.closest('a')) return
const list = [...scope.querySelectorAll('img')].map((i) => i.dataset.fullsrc || i.currentSrc || i.src)
const cur = img.dataset.fullsrc || img.currentSrc || img.src
const idx = Math.max(0, list.indexOf(cur))
e.stopPropagation()
openLightbox(list, idx)
}
// 正文代码块复制按钮(事件委托:复制按钮是 enhanceProse 注入的静态 HTML)
function onCopyClick(e) {
const btn = e.target.closest?.('.pre-copy')
@@ -31,8 +48,14 @@ function onCopyClick(e) {
setTimeout(() => (btn.textContent = '复制'), 1600)
})
}
onMounted(() => document.addEventListener('click', onCopyClick))
onBeforeUnmount(() => document.removeEventListener('click', onCopyClick))
onMounted(() => {
document.addEventListener('click', onCopyClick)
document.addEventListener('click', onProseImgClick, true)
})
onBeforeUnmount(() => {
document.removeEventListener('click', onCopyClick)
document.removeEventListener('click', onProseImgClick, true)
})
const isAdmin = computed(() => route.path.startsWith('/admin'))
// vivid 只在公开前台生效:后台永远走 classic 那套(--admin-* token + 原 data-ui/data-theme),