fix: 修复首页空白、小红书/游记封面图、定制页二维码
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>
这个提交包含在:
@@ -126,6 +126,17 @@ function addNote() {
|
||||
async function save() {
|
||||
saving.value = true
|
||||
try {
|
||||
// 自动下载外部封面图到本地
|
||||
for (const note of data.value.notes) {
|
||||
if (note.cover && note.cover.startsWith('http')) {
|
||||
try {
|
||||
const res = await adminFetch('/api/admin/download-image', { method: 'POST', body: { url: note.cover } })
|
||||
note.cover = res.localUrl
|
||||
} catch {
|
||||
// 下载失败保留原 URL,不阻断保存
|
||||
}
|
||||
}
|
||||
}
|
||||
await adminFetch('/api/admin/site-content', { method: 'PUT', body: { key: 'xiaohongshu-wall', data: data.value } })
|
||||
message.success('已保存')
|
||||
} catch {
|
||||
|
||||
@@ -113,6 +113,17 @@ function addNote() {
|
||||
async function save() {
|
||||
saving.value = true
|
||||
try {
|
||||
// 自动下载外部封面图到本地
|
||||
for (const note of data.value.notes) {
|
||||
if (note.cover && note.cover.startsWith('http')) {
|
||||
try {
|
||||
const res = await adminFetch('/api/admin/download-image', { method: 'POST', body: { url: note.cover } })
|
||||
note.cover = res.localUrl
|
||||
} catch {
|
||||
// 下载失败保留原 URL,不阻断保存
|
||||
}
|
||||
}
|
||||
}
|
||||
await adminFetch('/api/admin/site-content', { method: 'PUT', body: { key: 'youji', data: data.value } })
|
||||
message.success('已保存')
|
||||
} catch {
|
||||
|
||||
+16
-12
@@ -46,7 +46,7 @@
|
||||
</p>
|
||||
<div class="success-wechat">
|
||||
<span class="wechat-label">也可主动添加定制师微信</span>
|
||||
<span class="wechat-id">{{ customize.contact.wechat }}</span>
|
||||
<img src="/images/contact/qrcode-wechat.jpg" alt="定制师微信二维码" class="wechat-qrcode wechat-qrcode--success" />
|
||||
</div>
|
||||
<p class="success-tip">{{ customize.contact.tip }}</p>
|
||||
<button class="btn-reset" @click="resetForm">重新填写</button>
|
||||
@@ -249,8 +249,8 @@
|
||||
|
||||
<div class="aside-card aside-wechat">
|
||||
<h3 class="aside-title">不想填表?</h3>
|
||||
<p class="aside-desc">直接添加定制师微信,随时咨询:</p>
|
||||
<div class="wechat-id-display">{{ customize.contact.wechat }}</div>
|
||||
<p class="aside-desc">扫码添加定制师微信,随时咨询:</p>
|
||||
<img src="/images/contact/qrcode-wechat.jpg" alt="定制师微信二维码" class="wechat-qrcode" />
|
||||
<p class="wechat-tip">{{ customize.contact.tip }}</p>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -974,16 +974,20 @@ select,
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.wechat-id-display {
|
||||
font-size: @font-size-lg;
|
||||
font-weight: 700;
|
||||
color: @color-primary;
|
||||
padding: @space-sm @space-md;
|
||||
background: @color-bg-white;
|
||||
.wechat-qrcode {
|
||||
display: block;
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
object-fit: contain;
|
||||
margin: @space-sm auto;
|
||||
border-radius: @border-radius-md;
|
||||
text-align: center;
|
||||
margin-bottom: @space-sm;
|
||||
letter-spacing: 1px;
|
||||
border: 1px solid @color-border;
|
||||
background: @color-bg-white;
|
||||
|
||||
&--success {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
}
|
||||
}
|
||||
|
||||
.wechat-tip {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<main class="detail-main">
|
||||
<!-- 封面图 -->
|
||||
<div class="detail-cover" :class="{ 'detail-cover--wide': note.ratio === 'horizontal' }">
|
||||
<img :src="note.cover" :alt="note.title" />
|
||||
<img :src="proxyImage(note.cover)" :alt="note.title" referrerpolicy="no-referrer" />
|
||||
</div>
|
||||
|
||||
<!-- 笔记正文预览 -->
|
||||
@@ -126,7 +126,7 @@
|
||||
:class="{ 'sidebar-note--active': n.id === note.id }"
|
||||
>
|
||||
<NuxtLink :to="`/xiaohongshu/${n.id}`" class="sidebar-note__link">
|
||||
<img :src="n.cover" :alt="n.title" class="sidebar-note__thumb" />
|
||||
<img :src="proxyImage(n.cover)" :alt="n.title" class="sidebar-note__thumb" referrerpolicy="no-referrer" />
|
||||
<div class="sidebar-note__info">
|
||||
<span class="sidebar-note__title">{{ n.title }}</span>
|
||||
<span class="sidebar-note__author">@{{ n.author }}</span>
|
||||
@@ -163,6 +163,7 @@
|
||||
|
||||
<script setup>
|
||||
import { useBreadcrumbSchema } from '~/composables/useJsonLd'
|
||||
import { proxyImage } from '~/composables/useImageProxy'
|
||||
|
||||
const { data: wallData } = await usePublicApi('xiaohongshu-wall')
|
||||
|
||||
|
||||
@@ -102,9 +102,10 @@
|
||||
>
|
||||
<div class="note-card__cover" :class="{ 'note-card__cover--wide': note.ratio === 'horizontal' }">
|
||||
<img
|
||||
:src="note.cover"
|
||||
:src="proxyImage(note.cover)"
|
||||
:alt="note.title"
|
||||
loading="lazy"
|
||||
referrerpolicy="no-referrer"
|
||||
@error="handleImageError"
|
||||
/>
|
||||
<div class="note-card__overlay">
|
||||
@@ -160,6 +161,7 @@
|
||||
|
||||
<script setup>
|
||||
import { useBreadcrumbSchema } from '~/composables/useJsonLd'
|
||||
import { proxyImage } from '~/composables/useImageProxy'
|
||||
|
||||
const { data: wallData } = await usePublicApi('xiaohongshu-wall')
|
||||
|
||||
|
||||
+3
-2
@@ -13,7 +13,7 @@
|
||||
<main class="detail-main">
|
||||
<!-- 封面 -->
|
||||
<div class="detail-cover" :class="{ 'detail-cover--wide': note.ratio === 'horizontal' }">
|
||||
<img :src="note.cover" :alt="note.title" />
|
||||
<img :src="proxyImage(note.cover)" :alt="note.title" referrerpolicy="no-referrer" />
|
||||
</div>
|
||||
|
||||
<!-- 正文 -->
|
||||
@@ -97,7 +97,7 @@
|
||||
:class="{ 'sidebar-note--active': n.id === note.id }"
|
||||
>
|
||||
<NuxtLink :to="`/youji/${n.id}`" class="sidebar-note__link">
|
||||
<img :src="n.cover" :alt="n.title" class="sidebar-note__thumb" />
|
||||
<img :src="proxyImage(n.cover)" :alt="n.title" class="sidebar-note__thumb" referrerpolicy="no-referrer" />
|
||||
<div class="sidebar-note__info">
|
||||
<span class="sidebar-note__title">{{ n.title }}</span>
|
||||
<span class="sidebar-note__meta">
|
||||
@@ -143,6 +143,7 @@
|
||||
|
||||
<script setup>
|
||||
import { useBreadcrumbSchema } from '~/composables/useJsonLd'
|
||||
import { proxyImage } from '~/composables/useImageProxy'
|
||||
|
||||
const { data: youjiData } = await usePublicApi('youji')
|
||||
|
||||
|
||||
+2
-1
@@ -93,7 +93,7 @@
|
||||
class="note-card"
|
||||
>
|
||||
<div class="note-card__cover" :class="{ 'note-card__cover--wide': note.ratio === 'horizontal' }">
|
||||
<img :src="note.cover" :alt="note.title" loading="lazy" @error="handleImageError" />
|
||||
<img :src="proxyImage(note.cover)" :alt="note.title" loading="lazy" referrerpolicy="no-referrer" @error="handleImageError" />
|
||||
<div class="note-card__overlay">
|
||||
<span class="note-card__read">查看详情</span>
|
||||
</div>
|
||||
@@ -136,6 +136,7 @@
|
||||
|
||||
<script setup>
|
||||
import { useBreadcrumbSchema } from '~/composables/useJsonLd'
|
||||
import { proxyImage } from '~/composables/useImageProxy'
|
||||
|
||||
const { data: youjiData } = await usePublicApi('youji')
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户