diff --git a/game-studio/src/components/GameCard.vue b/game-studio/src/components/GameCard.vue index 83d71b92..3b7ab0e1 100644 --- a/game-studio/src/components/GameCard.vue +++ b/game-studio/src/components/GameCard.vue @@ -7,6 +7,7 @@ */ import { computed } from 'vue' import type { FeedCard } from '../api/types' +import { resolveCoverStyle } from '../utils/coverGradient' const props = defineProps<{ /** 游戏流卡片数据(严格贴契约 FeedCard) */ @@ -33,6 +34,26 @@ const hasCover = computed(() => { const url = props.card.coverUrl return !!url && !PLACEHOLDER_COVER_RE.test(url) }) + +/** + * 无封面时的确定性渐变兜底样式(spec §3.3 V-2):按 title(兜底 gameId)算稳定 hash, + * 取 ≥3 套青绿/青紫/暖色系渐变 + 柔光点 + 波形装饰之一,让无图卡也有辨识度、不千篇一律。 + * 仅在 !hasCover 时计算并下发到 CSS 变量(有真封面时为 null,不渲染兜底装饰)。 + */ +const coverFallback = computed(() => (hasCover.value ? null : resolveCoverStyle(props.card))) +/** 兜底底纹的内联 CSS 变量(渐变/柔光色/波形色/柔光落位);有真封面时返回空对象。 */ +const fallbackVars = computed>(() => { + const f = coverFallback.value + const vars: Record = {} + if (!f) return vars + vars['--cover-grad'] = f.theme.gradient + vars['--cover-glow'] = f.theme.glow + vars['--cover-wave'] = f.theme.wave + vars['--cover-glow-top'] = f.decor.glowTop + vars['--cover-glow-right'] = f.decor.glowRight + // 波形相位不走 CSS 变量,改用模板上的 --wave{N} 类切换 clip-path(见 template :class) + return vars +})