1. 首页大面积空白:useScrollReveal 添加 MutationObserver, 确保异步子组件的 .reveal 元素也能触发入场动画 2. 小红书/游记封面图不显示: - 小红书 CDN 签名链接过期+防盗链,全部下载到本地 - 新增 download-covers.mjs 脚本批量下载封面 - 新增 useImageProxy composable 转换外部 URL - 页面 img 标签添加 referrerpolicy="no-referrer" - 管理端保存时自动下载外部封面图到本地 - 种子数据更新为本地路径 3. 定制页微信号文字替换为二维码图片 4. prerender 路由添加 /xiaohongshu 和 /youji Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
46 行
1.3 KiB
JavaScript
46 行
1.3 KiB
JavaScript
/**
|
|
* 滚动入场动画 composable
|
|
* 元素进入视口时触发淡入上滑动画
|
|
* 自动尊重 prefers-reduced-motion
|
|
* 使用 MutationObserver 确保异步渲染的子组件也能被观察到
|
|
*/
|
|
export default function useScrollReveal() {
|
|
onMounted(() => {
|
|
// 尊重用户减少动效偏好
|
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return
|
|
|
|
const io = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('is-visible')
|
|
io.unobserve(entry.target)
|
|
}
|
|
})
|
|
},
|
|
{ threshold: 0.1, rootMargin: '0px 0px -40px 0px' }
|
|
)
|
|
|
|
// 观察当前已有的 .reveal 元素
|
|
const observed = new WeakSet()
|
|
function observeAll() {
|
|
document.querySelectorAll('.reveal:not(.is-visible)').forEach((el) => {
|
|
if (!observed.has(el)) {
|
|
observed.add(el)
|
|
io.observe(el)
|
|
}
|
|
})
|
|
}
|
|
observeAll()
|
|
|
|
// 监听 DOM 变化,捕获异步渲染的子组件中的 .reveal 元素
|
|
const mo = new MutationObserver(observeAll)
|
|
mo.observe(document.body, { childList: true, subtree: true })
|
|
|
|
onUnmounted(() => {
|
|
io.disconnect()
|
|
mo.disconnect()
|
|
})
|
|
})
|
|
}
|