feat(home): 首页展示位空数据时渲染内置渐变图兜底
/showcase 返回空时 hero 拼贴与作品墙不再留白—— 用 public/showcase 下 11 张内置 SVG 渐变图填充; 接口有数据时仍优先使用后台配置的展示图。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="800" viewBox="0 0 600 800">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#7c5cf5"/><stop offset="55%" stop-color="#ec4899"/><stop offset="100%" stop-color="#f59e0b"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.5"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffd1e8" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffd1e8" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="600" height="800" fill="url(#g)"/>
|
||||
<rect width="600" height="800" fill="url(#b1)"/>
|
||||
<rect width="600" height="800" fill="url(#b2)"/>
|
||||
<circle cx="432" cy="240" r="54" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 496 Q 180 400 330 496 T 600 440.00000000000006 V 800 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 576 Q 210 480 360 576 T 600 528 V 800 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="800" viewBox="0 0 600 800">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#0ea5e9"/><stop offset="60%" stop-color="#6366f1"/><stop offset="100%" stop-color="#1e1b4b"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#bae6fd" stop-opacity="0.5"/><stop offset="100%" stop-color="#bae6fd" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="600" height="800" fill="url(#g)"/>
|
||||
<rect width="600" height="800" fill="url(#b1)"/>
|
||||
<rect width="600" height="800" fill="url(#b2)"/>
|
||||
<circle cx="432" cy="240" r="54" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 496 Q 180 400 330 496 T 600 440.00000000000006 V 800 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 576 Q 210 480 360 576 T 600 528 V 800 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600" viewBox="0 0 600 600">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#f59e0b"/><stop offset="50%" stop-color="#ef4444"/><stop offset="100%" stop-color="#7c2d12"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#fde68a" stop-opacity="0.5"/><stop offset="100%" stop-color="#fde68a" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="600" height="600" fill="url(#g)"/>
|
||||
<rect width="600" height="600" fill="url(#b1)"/>
|
||||
<rect width="600" height="600" fill="url(#b2)"/>
|
||||
<circle cx="432" cy="180" r="54" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 372 Q 180 300 330 372 T 600 330 V 600 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 432 Q 210 360 360 432 T 600 396 V 600 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="800" viewBox="0 0 600 800">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#10b981"/><stop offset="60%" stop-color="#0ea5e9"/><stop offset="100%" stop-color="#0f172a"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#a7f3d0" stop-opacity="0.5"/><stop offset="100%" stop-color="#a7f3d0" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="600" height="800" fill="url(#g)"/>
|
||||
<rect width="600" height="800" fill="url(#b1)"/>
|
||||
<rect width="600" height="800" fill="url(#b2)"/>
|
||||
<circle cx="432" cy="240" r="54" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 496 Q 180 400 330 496 T 600 440.00000000000006 V 800 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 576 Q 210 480 360 576 T 600 528 V 800 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="534" viewBox="0 0 800 534">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#8b5cf6"/><stop offset="100%" stop-color="#4f46e5"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#c4b5fd" stop-opacity="0.5"/><stop offset="100%" stop-color="#c4b5fd" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="800" height="534" fill="url(#g)"/>
|
||||
<rect width="800" height="534" fill="url(#b1)"/>
|
||||
<rect width="800" height="534" fill="url(#b2)"/>
|
||||
<circle cx="576" cy="160.2" r="72" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 331.08 Q 240 267 440.00000000000006 331.08 T 800 293.70000000000005 V 534 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 384.47999999999996 Q 280 320.4 480 384.47999999999996 T 800 352.44 V 534 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="534" viewBox="0 0 800 534">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#ec4899"/><stop offset="100%" stop-color="#8b5cf6"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#fbcfe8" stop-opacity="0.5"/><stop offset="100%" stop-color="#fbcfe8" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="800" height="534" fill="url(#g)"/>
|
||||
<rect width="800" height="534" fill="url(#b1)"/>
|
||||
<rect width="800" height="534" fill="url(#b2)"/>
|
||||
<circle cx="576" cy="160.2" r="72" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 331.08 Q 240 267 440.00000000000006 331.08 T 800 293.70000000000005 V 534 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 384.47999999999996 Q 280 320.4 480 384.47999999999996 T 800 352.44 V 534 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="534" viewBox="0 0 800 534">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#22d3ee"/><stop offset="100%" stop-color="#3b82f6"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#a5f3fc" stop-opacity="0.5"/><stop offset="100%" stop-color="#a5f3fc" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="800" height="534" fill="url(#g)"/>
|
||||
<rect width="800" height="534" fill="url(#b1)"/>
|
||||
<rect width="800" height="534" fill="url(#b2)"/>
|
||||
<circle cx="576" cy="160.2" r="72" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 331.08 Q 240 267 440.00000000000006 331.08 T 800 293.70000000000005 V 534 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 384.47999999999996 Q 280 320.4 480 384.47999999999996 T 800 352.44 V 534 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="534" viewBox="0 0 800 534">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#f97316"/><stop offset="100%" stop-color="#ec4899"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#fed7aa" stop-opacity="0.5"/><stop offset="100%" stop-color="#fed7aa" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="800" height="534" fill="url(#g)"/>
|
||||
<rect width="800" height="534" fill="url(#b1)"/>
|
||||
<rect width="800" height="534" fill="url(#b2)"/>
|
||||
<circle cx="576" cy="160.2" r="72" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 331.08 Q 240 267 440.00000000000006 331.08 T 800 293.70000000000005 V 534 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 384.47999999999996 Q 280 320.4 480 384.47999999999996 T 800 352.44 V 534 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="534" viewBox="0 0 800 534">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#6366f1"/><stop offset="100%" stop-color="#22d3ee"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#c7d2fe" stop-opacity="0.5"/><stop offset="100%" stop-color="#c7d2fe" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="800" height="534" fill="url(#g)"/>
|
||||
<rect width="800" height="534" fill="url(#b1)"/>
|
||||
<rect width="800" height="534" fill="url(#b2)"/>
|
||||
<circle cx="576" cy="160.2" r="72" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 331.08 Q 240 267 440.00000000000006 331.08 T 800 293.70000000000005 V 534 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 384.47999999999996 Q 280 320.4 480 384.47999999999996 T 800 352.44 V 534 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="534" viewBox="0 0 800 534">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#14b8a6"/><stop offset="100%" stop-color="#84cc16"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#99f6e4" stop-opacity="0.5"/><stop offset="100%" stop-color="#99f6e4" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="800" height="534" fill="url(#g)"/>
|
||||
<rect width="800" height="534" fill="url(#b1)"/>
|
||||
<rect width="800" height="534" fill="url(#b2)"/>
|
||||
<circle cx="576" cy="160.2" r="72" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 331.08 Q 240 267 440.00000000000006 331.08 T 800 293.70000000000005 V 534 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 384.47999999999996 Q 280 320.4 480 384.47999999999996 T 800 352.44 V 534 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="534" viewBox="0 0 800 534">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#a855f7"/><stop offset="100%" stop-color="#6366f1"/></linearGradient>
|
||||
<radialGradient id="b1" cx="0.3" cy="0.25" r="0.7"><stop offset="0%" stop-color="#e9d5ff" stop-opacity="0.5"/><stop offset="100%" stop-color="#e9d5ff" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="b2" cx="0.75" cy="0.75" r="0.6"><stop offset="0%" stop-color="#ffffff" stop-opacity="0.28"/><stop offset="100%" stop-color="#ffffff" stop-opacity="0"/></radialGradient>
|
||||
</defs>
|
||||
<rect width="800" height="534" fill="url(#g)"/>
|
||||
<rect width="800" height="534" fill="url(#b1)"/>
|
||||
<rect width="800" height="534" fill="url(#b2)"/>
|
||||
<circle cx="576" cy="160.2" r="72" fill="rgba(255,255,255,0.5)"/>
|
||||
<path d="M0 331.08 Q 240 267 440.00000000000006 331.08 T 800 293.70000000000005 V 534 H0 Z" fill="rgba(255,255,255,0.12)"/>
|
||||
<path d="M0 384.47999999999996 Q 280 320.4 480 384.47999999999996 T 800 352.44 V 534 H0 Z" fill="rgba(255,255,255,0.1)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -207,6 +207,16 @@ const PH_SLOTS = [
|
||||
]
|
||||
const heroSlots = computed(() => (carouselLoading.value && !carouselItems.value.length) ? PH_SLOTS : carouselItems.value.slice(0, 4))
|
||||
const inspireItems = ref([])
|
||||
// 后台未配置展示位时的内置兜底图(/public/showcase 下的本地渐变图)
|
||||
const FALLBACK_HERO = [
|
||||
{ id: 'fb-h1', title: '霓虹都市', prompt: '雨夜霓虹街道,赛博朋克光影', image: '/showcase/hero-1.svg' },
|
||||
{ id: 'fb-h2', title: '深海蓝调', prompt: '深海蓝调梦境,光斑浮动', image: '/showcase/hero-2.svg' },
|
||||
{ id: 'fb-h3', title: '熔金落日', prompt: '熔金色落日余晖', image: '/showcase/hero-3.svg' },
|
||||
{ id: 'fb-h4', title: '翡翠星野', prompt: '翡翠色星野与极光', image: '/showcase/hero-4.svg' },
|
||||
]
|
||||
const FALLBACK_WORKS = [1, 2, 3, 4, 5, 6, 7].map(i => ({
|
||||
id: 'fb-w' + i, title: '灵感作品 ' + i, prompt: '', image: `/showcase/work-${i}.svg`,
|
||||
}))
|
||||
// Hero 拼贴固定 4 格;后端已限制轮播最多 4 张,此处 slice 兜底
|
||||
const heroArts = computed(() => carouselItems.value.slice(0, 4))
|
||||
|
||||
@@ -221,11 +231,17 @@ onMounted(async () => {
|
||||
])
|
||||
onlineModels.value = (m.data?.data || []).filter(model => model.sellable)
|
||||
const data = sc.data?.data || {}
|
||||
// hero 拼贴优先取 hero 位,不足 4 张用 bento 补齐
|
||||
carouselItems.value = [...(data.hero || []), ...(data.bento || [])].filter(i => i.image).slice(0, 4)
|
||||
inspireItems.value = data.work || []
|
||||
// hero 拼贴按 hero → bento → 作品墙兜底取图,保证首屏有图可看
|
||||
const pool = [...(data.hero || []), ...(data.bento || []), ...(data.work || [])]
|
||||
carouselItems.value = pool.filter(i => i.image).slice(0, 4)
|
||||
if (!carouselItems.value.length) carouselItems.value = FALLBACK_HERO
|
||||
inspireItems.value = (data.work || []).length ? data.work : FALLBACK_WORKS
|
||||
carouselLoading.value = false
|
||||
} catch { carouselLoading.value = false /* 展示位加载失败不阻塞首页 */ }
|
||||
} catch {
|
||||
carouselItems.value = FALLBACK_HERO
|
||||
inspireItems.value = FALLBACK_WORKS
|
||||
carouselLoading.value = false /* 展示位加载失败不阻塞首页 */
|
||||
}
|
||||
await nextTick()
|
||||
if (typeof IntersectionObserver === 'undefined') return
|
||||
revealObs = new IntersectionObserver((entries) => {
|
||||
@@ -278,7 +294,9 @@ const features = computed(() => {
|
||||
// (like "user/abc.png") are served from /images by the backend.
|
||||
function imgSrc(image) {
|
||||
if (!image) return ''
|
||||
return /^https?:\/\//i.test(image) ? image : generatedUrl(image)
|
||||
if (/^https?:\/\//i.test(image)) return image
|
||||
if (image.startsWith('/')) return image // 内置静态资源(public/ 下)
|
||||
return generatedUrl(image)
|
||||
}
|
||||
|
||||
async function copyQqGroup() {
|
||||
|
||||