fix: 升级了一些视觉

This commit is contained in:
2026-08-12 13:53:06 +08:00
parent 5fb0f9a1a7
commit 5e609d5ee4
9 changed files with 2347 additions and 0 deletions

View File

@@ -0,0 +1,225 @@
<template>
<div class="sh" :class="`sh-${kind}`">
<span v-if="indexText" class="sh-index">{{ indexText }}</span>
<span v-if="kicker" class="sh-kicker">{{ kicker }}</span>
<i class="sh-rule sh-rule-top" aria-hidden="true"></i>
<span class="sh-title">{{ title }}</span>
<i class="sh-rule sh-rule-bottom" aria-hidden="true"></i>
<span v-if="note" class="sh-note">{{ note }}</span>
</div>
</template>
<script setup>
/**
* 完整模板layout 主题)的统一章节头。
* 结构固定,观感按 html[data-theme]magazine/newspaper/pixel/zen差异化
* - magazine 左对齐编号大字
* - newspaper 居中栏目头,双细线夹标题
* - pixel 像素方框标题
* - zen 小字 + 细线 + 大留白
* pack 主题不使用本组件(各区块保留原有专属设计)。
*/
import { computed } from 'vue'
const props = defineProps({
title: { type: String, default: '' },
kicker: { type: String, default: '' },
note: { type: String, default: '' },
/** 章节序号(杂志风显示为 01/02… */
index: { type: Number, default: 0 },
/** 当前主题 key用于组件内微调可不传 */
kind: { type: String, default: 'layout' },
})
const indexText = computed(() => (props.index > 0 ? String(props.index).padStart(2, '0') : ''))
</script>
<style scoped>
.sh {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: 6px;
margin-bottom: 22px;
}
.sh-index {
display: none;
font-family: var(--font-display);
font-style: italic;
line-height: 1;
color: rgba(var(--c-primary-rgb), 0.34);
}
.sh-kicker {
font-family: var(--t-font-kicker);
font-size: 11px;
letter-spacing: 0.34em;
text-transform: uppercase;
color: var(--c-muted);
}
.sh-title {
font-family: var(--t-font-title);
font-size: 24px;
letter-spacing: 0.16em;
color: var(--c-ink);
line-height: 1.3;
}
.sh-note {
font-size: 11px;
letter-spacing: 0.12em;
color: var(--c-muted);
max-width: 300px;
line-height: 1.9;
white-space: pre-wrap;
}
.sh-rule {
display: none;
pointer-events: none;
}
/* —— 新中式:宋体 + 端部朱砂方点 + 细黛线 —— */
html[data-theme='guofeng-new'] .sh-kicker {
font-family: var(--font-kai);
letter-spacing: 0.44em;
}
html[data-theme='guofeng-new'] .sh-title {
font-family: var(--font-serif);
font-weight: 600;
letter-spacing: 0.3em;
text-indent: 0.3em;
}
html[data-theme='guofeng-new'] .sh-rule-bottom {
display: block;
width: 8px;
height: 8px;
background: #b5493f;
border-radius: 1px;
margin-top: 2px;
}
/* —— 老中式:楷体横批 + 金线双边 —— */
html[data-theme='guofeng-old'] .sh-kicker {
font-family: var(--font-kai);
letter-spacing: 0.4em;
color: var(--c-line);
}
html[data-theme='guofeng-old'] .sh-title {
font-family: var(--font-kai);
font-weight: 700;
letter-spacing: 0.4em;
text-indent: 0.4em;
color: var(--c-primary);
}
html[data-theme='guofeng-old'] .sh-rule {
display: block;
width: min(220px, 62%);
height: 5px;
border-top: 1px solid rgba(var(--c-line-rgb), 0.85);
border-bottom: 1px solid rgba(var(--c-line-rgb), 0.45);
}
/* —— 杂志封面:左对齐、超大编号、大写大字距 —— */
html[data-theme='magazine'] .sh {
align-items: flex-start;
text-align: left;
padding-left: 2px;
gap: 2px;
}
html[data-theme='magazine'] .sh-index {
display: block;
font-size: 52px;
margin-bottom: 2px;
}
html[data-theme='magazine'] .sh-kicker {
font-size: 10px;
letter-spacing: 0.5em;
color: var(--c-primary);
}
html[data-theme='magazine'] .sh-title {
font-family: var(--font-display);
font-size: 30px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
}
html[data-theme='magazine'] .sh-rule-top {
display: block;
order: -1;
width: 44px;
height: 3px;
background: var(--c-ink);
margin-bottom: 8px;
}
html[data-theme='magazine'] .sh-note {
text-align: left;
}
/* —— 日报编辑:居中栏目头,双细线夹标题 —— */
html[data-theme='newspaper'] .sh {
gap: 8px;
}
html[data-theme='newspaper'] .sh-kicker {
font-family: var(--font-display);
font-size: 10px;
letter-spacing: 0.44em;
}
html[data-theme='newspaper'] .sh-title {
font-family: var(--font-serif);
font-weight: 700;
font-size: 25px;
letter-spacing: 0.22em;
}
html[data-theme='newspaper'] .sh-rule {
display: block;
width: min(240px, 68%);
height: 3px;
border-top: 1px solid var(--c-ink);
border-bottom: 1px solid var(--c-ink);
}
html[data-theme='newspaper'] .sh-note {
font-family: var(--font-serif);
font-style: italic;
}
/* —— 复古像素:像素方框标题 —— */
html[data-theme='pixel'] .sh-kicker {
font-size: 10px;
letter-spacing: 0.2em;
color: var(--c-line);
}
html[data-theme='pixel'] .sh-title {
font-size: 19px;
letter-spacing: 0.1em;
padding: 8px 16px;
color: var(--c-primary);
border: 3px solid var(--c-primary);
box-shadow: 4px 4px 0 rgba(var(--c-line-rgb), 0.55);
image-rendering: pixelated;
}
html[data-theme='pixel'] .sh-note {
font-size: 10px;
}
/* —— 极简主义:小字 + 一条细线 + 大留白 —— */
html[data-theme='zen'] .sh {
gap: 12px;
margin-bottom: 34px;
}
html[data-theme='zen'] .sh-kicker {
font-size: 9px;
letter-spacing: 0.6em;
}
html[data-theme='zen'] .sh-title {
font-size: 20px;
font-weight: 300;
letter-spacing: 0.5em;
text-indent: 0.5em;
}
html[data-theme='zen'] .sh-rule-bottom {
display: block;
width: 1px;
height: 26px;
background: rgba(var(--c-line-rgb), 0.6);
}
</style>

View File

@@ -0,0 +1,39 @@
<template>
<div class="flex flex-col items-center justify-between py-12 flex-1 w-full relative border-[0.5px] border-[var(--c-primary)]/20 bg-[var(--c-card)]/40">
<div v-reveal="'down'" class="text-center mt-6 z-10">
<span class="cover-kicker calligraphy text-[10px] tracking-[0.5em] uppercase text-[var(--c-primary)] font-bold block">Wedding Invitation</span>
<div class="w-6 h-[0.5px] bg-[var(--c-primary)] mx-auto opacity-50 mt-4"></div>
</div>
<div v-reveal="{ variant: 'scale', delay: 120 }" class="w-full max-w-[260px] aspect-[3/4] relative z-10">
<div class="absolute inset-0 border border-[var(--c-primary)] translate-x-3 translate-y-3 opacity-30"></div>
<div class="relative w-full h-full z-10 bg-[var(--c-bg)] shadow-md overflow-hidden">
<img :src="heroImg" class="w-full h-full object-cover" fetchpriority="high" decoding="async" alt="封面" />
</div>
</div>
<div v-reveal="{ variant: 'up', delay: 200 }" class="text-center z-10 mb-10 space-y-4 px-4 mt-8">
<div class="cover-names calligraphy-strong flex items-end justify-center gap-6 text-3xl font-light tracking-[0.2em]">
<span>{{ groom }}</span>
<span class="text-[var(--c-primary)] text-xl pb-1 italic calligraphy">&amp;</span>
<span>{{ bride }}</span>
</div>
<div class="cover-date flex flex-col items-center text-[11px] text-[var(--c-muted)] tracking-[0.2em] mt-4 uppercase">
<span>{{ date }}</span>
<div class="w-4 h-[0.5px] bg-[var(--c-primary)]/40 my-2"></div>
<span>{{ lunar }}</span>
</div>
</div>
</div>
</template>
<script setup>
/** 经典封面(风格包主题共用):卡幅居中 + 偏移描边框,自 index.vue 迁出 */
defineProps({
heroImg: { type: String, default: '' },
groom: { type: String, default: '' },
bride: { type: String, default: '' },
date: { type: String, default: '' },
lunar: { type: String, default: '' },
})
</script>

View File

@@ -0,0 +1,143 @@
<template>
<div class="gn-root">
<svg v-reveal="'down'" class="gn-plum" viewBox="0 0 120 150" aria-hidden="true">
<g fill="none" stroke="var(--c-primary)" stroke-opacity="0.55" stroke-width="1.4" stroke-linecap="round">
<path d="M96 8C82 40 74 76 78 128" />
<path d="M84 52c-12 4-20 12-24 24" />
<path d="M80 92c10 2 18 8 22 18" />
</g>
<g fill="#b5493f" fill-opacity="0.85">
<circle cx="58" cy="72" r="3.4" />
<circle cx="52" cy="80" r="2.4" />
<circle cx="99" cy="106" r="3" />
<circle cx="106" cy="112" r="2.2" />
<circle cx="90" cy="30" r="2.6" />
</g>
<g fill="none" stroke="#b5493f" stroke-opacity="0.6" stroke-width="1">
<circle cx="66" cy="64" r="2.6" />
<circle cx="108" cy="98" r="2.4" />
</g>
</svg>
<span v-reveal="'down'" class="gn-kicker"> · </span>
<div v-reveal="{ variant: 'scale', delay: 160 }" class="gn-moon">
<img :src="heroImg" class="gn-img" fetchpriority="high" decoding="async" alt="封面" />
</div>
<div v-reveal="{ variant: 'up', delay: 280 }" class="gn-names">
<span>{{ groom }}</span>
<span class="gn-seal" aria-hidden="true"></span>
<span>{{ bride }}</span>
</div>
<div v-reveal="{ variant: 'up', delay: 360 }" class="gn-date">
<span>{{ date }}</span>
<i aria-hidden="true"></i>
<span>{{ lunar }}</span>
</div>
</div>
</template>
<script setup>
/** 新中式封面:米白留白 + 月洞门圆窗照片 + 梅枝线描 + 朱砂小印 */
defineProps({
heroImg: { type: String, default: '' },
groom: { type: String, default: '' },
bride: { type: String, default: '' },
date: { type: String, default: '' },
lunar: { type: String, default: '' },
})
</script>
<style scoped>
.gn-root {
position: relative;
width: 100%;
flex: 1 1 auto;
min-height: 100dvh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 30px;
padding: max(30px, env(safe-area-inset-top)) 26px 40px;
background: var(--c-bg);
overflow: hidden;
}
.gn-plum {
position: absolute;
top: max(10px, env(safe-area-inset-top));
right: 6px;
width: 108px;
height: 136px;
pointer-events: none;
}
.gn-kicker {
font-family: var(--font-kai);
font-size: 12px;
letter-spacing: 0.5em;
text-indent: 0.5em;
color: var(--c-muted);
}
/* 月洞门:双环细边圆窗 */
.gn-moon {
width: min(66vw, 250px);
aspect-ratio: 1;
border-radius: 50%;
padding: 9px;
border: 1px solid rgba(var(--c-primary-rgb), 0.55);
box-shadow:
inset 0 0 0 4px var(--c-bg),
inset 0 0 0 5px rgba(var(--c-line-rgb), 0.6),
0 18px 40px rgba(44, 48, 44, 0.12);
background: var(--c-card);
}
.gn-img {
width: 100%;
height: 100%;
border-radius: 50%;
object-fit: cover;
}
.gn-names {
display: flex;
align-items: center;
gap: 18px;
font-family: var(--font-serif);
font-size: clamp(22px, 6.6vw, 27px);
font-weight: 600;
letter-spacing: 0.3em;
text-indent: 0.3em;
color: var(--c-ink);
}
/* 朱砂方印 */
.gn-seal {
width: 34px;
height: 34px;
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-kai);
font-size: 17px;
letter-spacing: 0;
text-indent: 0;
color: #fdf6f0;
background: #b5493f;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(181, 73, 63, 0.35);
}
.gn-date {
display: flex;
align-items: center;
gap: 12px;
font-family: var(--font-serif);
font-size: 11px;
letter-spacing: 0.24em;
color: var(--c-muted);
}
.gn-date i {
width: 1px;
height: 12px;
background: rgba(var(--c-line-rgb), 0.6);
}
</style>

View File

@@ -0,0 +1,197 @@
<template>
<div class="go-root">
<div class="go-frame" aria-hidden="true"></div>
<span class="go-corner go-corner-tl" aria-hidden="true"></span>
<span class="go-corner go-corner-tr" aria-hidden="true"></span>
<span class="go-corner go-corner-bl" aria-hidden="true"></span>
<span class="go-corner go-corner-br" aria-hidden="true"></span>
<div v-reveal="'down'" class="go-tassels" aria-hidden="true">
<span class="go-tassel"><i></i><b></b></span>
<span class="go-kicker"> </span>
<span class="go-tassel"><i></i><b></b></span>
</div>
<div v-reveal="{ variant: 'scale', delay: 140 }" class="go-fan">
<img :src="heroImg" class="go-img" fetchpriority="high" decoding="async" alt="封面" />
</div>
<div v-reveal="{ variant: 'scale', delay: 260 }" class="go-xi calligraphy-strong"></div>
<div v-reveal="{ variant: 'up', delay: 340 }" class="go-names">
<span class="go-name">{{ groom }}</span>
<span class="go-name-dot" aria-hidden="true">·</span>
<span class="go-name">{{ bride }}</span>
</div>
<div v-reveal="{ variant: 'up', delay: 420 }" class="go-date">
<span>{{ date }}</span>
<span class="go-lunar">{{ lunar }}</span>
</div>
<div v-reveal="{ variant: 'up', delay: 480 }" class="go-foot" aria-hidden="true">
<i class="go-foot-line"></i>
<span> </span>
<i class="go-foot-line"></i>
</div>
</div>
</template>
<script setup>
/** 老中式封面:朱红鎏金婚书 —— 流苏、团扇照片、大囍、竖排气质金字 */
defineProps({
heroImg: { type: String, default: '' },
groom: { type: String, default: '' },
bride: { type: String, default: '' },
date: { type: String, default: '' },
lunar: { type: String, default: '' },
})
</script>
<style scoped>
.go-root {
position: relative;
width: 100%;
flex: 1 1 auto;
min-height: 100dvh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
padding: max(26px, env(safe-area-inset-top)) 26px 34px;
background:
radial-gradient(ellipse at 50% 12%, rgba(216, 90, 90, 0.35), transparent 46%),
linear-gradient(175deg, #b13a44 0%, #9c2f3a 45%, #822631 100%);
overflow: hidden;
color: var(--c-on-primary);
}
/* 金色内框(双线) */
.go-frame {
position: absolute;
inset: 14px;
border: 1px solid rgba(var(--c-line-rgb), 0.75);
outline: 1px solid rgba(var(--c-line-rgb), 0.35);
outline-offset: 4px;
pointer-events: none;
}
/* 回纹角(三层方折线) */
.go-corner {
position: absolute;
width: 26px;
height: 26px;
border: 2px solid rgba(var(--c-line-rgb), 0.9);
border-right: 0;
border-bottom: 0;
pointer-events: none;
}
.go-corner::before {
content: '';
position: absolute;
left: 4px;
top: 4px;
width: 12px;
height: 12px;
border: 2px solid rgba(var(--c-line-rgb), 0.55);
border-right: 0;
border-bottom: 0;
}
.go-corner-tl { top: 20px; left: 20px; }
.go-corner-tr { top: 20px; right: 20px; transform: scaleX(-1); }
.go-corner-bl { bottom: 20px; left: 20px; transform: scaleY(-1); }
.go-corner-br { bottom: 20px; right: 20px; transform: scale(-1); }
/* 顶部流苏 + 横批 */
.go-tassels {
display: flex;
align-items: flex-start;
gap: 22px;
}
.go-kicker {
font-family: var(--font-kai);
font-size: 15px;
letter-spacing: 0.5em;
text-indent: 0.5em;
color: var(--c-line);
padding-top: 4px;
}
.go-tassel {
display: flex;
flex-direction: column;
align-items: center;
}
.go-tassel i {
width: 1px;
height: 26px;
background: linear-gradient(180deg, rgba(var(--c-line-rgb), 0.9), rgba(var(--c-line-rgb), 0.5));
}
.go-tassel b {
width: 9px;
height: 16px;
border-radius: 2px 2px 4px 4px;
background: linear-gradient(180deg, var(--c-line), #a37f2e);
}
/* 团扇照片 */
.go-fan {
width: min(56vw, 210px);
aspect-ratio: 1;
border-radius: 50%;
padding: 6px;
background: linear-gradient(160deg, rgba(var(--c-line-rgb), 0.95), rgba(163, 127, 46, 0.9));
box-shadow: 0 14px 36px rgba(60, 10, 16, 0.45);
}
.go-img {
width: 100%;
height: 100%;
border-radius: 50%;
object-fit: cover;
border: 2px solid rgba(255, 246, 230, 0.5);
}
/* 大囍 */
.go-xi {
font-size: clamp(56px, 17vw, 78px);
line-height: 1;
color: var(--c-line);
text-shadow: 0 3px 14px rgba(40, 6, 10, 0.5);
}
.go-names {
display: flex;
align-items: baseline;
gap: 14px;
font-family: var(--font-kai);
font-size: clamp(23px, 7vw, 29px);
letter-spacing: 0.18em;
color: #f7e7c3;
}
.go-name-dot {
color: rgba(var(--c-line-rgb), 0.9);
}
.go-date {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
font-family: var(--font-kai);
font-size: 12px;
letter-spacing: 0.26em;
color: rgba(247, 231, 195, 0.85);
}
.go-lunar {
font-size: 11px;
opacity: 0.8;
}
.go-foot {
display: flex;
align-items: center;
gap: 12px;
font-family: var(--font-kai);
font-size: 12px;
letter-spacing: 0.5em;
text-indent: 0.5em;
color: var(--c-line);
}
.go-foot-line {
width: 40px;
height: 5px;
border-top: 1px solid rgba(var(--c-line-rgb), 0.7);
border-bottom: 1px solid rgba(var(--c-line-rgb), 0.4);
}
</style>

View File

@@ -0,0 +1,161 @@
<template>
<div class="cm-root">
<div class="cm-photo" aria-hidden="true">
<img :src="heroImg" class="cm-img" fetchpriority="high" decoding="async" alt="封面" />
<span class="cm-photo-veil"></span>
</div>
<div v-reveal="'down'" class="cm-masthead">
<span class="cm-logo">VOWS</span>
<span class="cm-issue">WEDDING ISSUE</span>
</div>
<div v-reveal="{ variant: 'right', delay: 160 }" class="cm-side" aria-hidden="true">
<span>{{ date }}</span>
</div>
<div class="cm-bottom">
<div v-reveal="{ variant: 'up', delay: 220 }" class="cm-headline">
<span class="cm-kicker">The Wedding Of</span>
<span class="cm-names">{{ groom }}<i>&amp;</i>{{ bride }}</span>
<span class="cm-sub">{{ lunar }} · 诚邀您见证</span>
</div>
<div v-reveal="{ variant: 'up', delay: 320 }" class="cm-barcode" aria-hidden="true">
<i v-for="n in 18" :key="n"></i>
</div>
</div>
</div>
</template>
<script setup>
/** 杂志封面:全幅大图打底、报头 LOGO、右缘竖排期号、左下贴边大字标题、条码装饰 */
defineProps({
heroImg: { type: String, default: '' },
groom: { type: String, default: '' },
bride: { type: String, default: '' },
date: { type: String, default: '' },
lunar: { type: String, default: '' },
})
</script>
<style scoped>
.cm-root {
position: relative;
width: 100%;
/* 父级 page-section 是 min-height 的 flex columnheight:100% 会塌陷,必须用 flex 拉伸 */
flex: 1 1 auto;
min-height: 100dvh;
overflow: hidden;
background: var(--c-bg-deep);
}
.cm-photo {
position: absolute;
inset: 0;
}
.cm-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.cm-photo-veil {
position: absolute;
inset: 0;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0) 32%, rgba(0, 0, 0, 0) 46%, rgba(0, 0, 0, 0.56) 100%);
}
.cm-masthead {
position: absolute;
top: max(20px, env(safe-area-inset-top));
left: 18px;
right: 18px;
z-index: 2;
display: flex;
align-items: baseline;
justify-content: space-between;
color: #fff;
}
.cm-logo {
font-family: var(--font-display);
font-weight: 700;
font-size: 40px;
letter-spacing: 0.14em;
line-height: 1;
text-shadow: 0 2px 14px rgba(0, 0, 0, 0.35);
}
.cm-issue {
font-family: var(--font-cinzel);
font-size: 10px;
letter-spacing: 0.42em;
opacity: 0.92;
}
.cm-side {
position: absolute;
right: 14px;
top: 50%;
transform: translateY(-50%);
z-index: 2;
writing-mode: vertical-rl;
font-family: var(--font-cinzel);
font-size: 10px;
letter-spacing: 0.4em;
color: rgba(255, 255, 255, 0.85);
border-right: 1px solid rgba(255, 255, 255, 0.4);
padding-right: 8px;
}
.cm-bottom {
position: absolute;
left: 18px;
right: 18px;
bottom: max(26px, env(safe-area-inset-bottom));
z-index: 2;
display: flex;
flex-direction: column;
gap: 14px;
}
.cm-headline {
display: flex;
flex-direction: column;
gap: 6px;
color: #fff;
}
.cm-kicker {
font-family: var(--font-cinzel);
font-size: 11px;
letter-spacing: 0.5em;
text-transform: uppercase;
opacity: 0.9;
}
.cm-names {
font-family: var(--font-display);
font-weight: 700;
font-size: clamp(34px, 11vw, 52px);
line-height: 1.12;
letter-spacing: 0.04em;
text-shadow: 0 3px 18px rgba(0, 0, 0, 0.4);
}
.cm-names i {
font-style: italic;
font-weight: 400;
margin: 0 0.18em;
opacity: 0.85;
}
.cm-sub {
font-size: 12px;
letter-spacing: 0.24em;
opacity: 0.88;
}
.cm-barcode {
display: flex;
align-items: flex-end;
gap: 2px;
height: 22px;
opacity: 0.9;
}
.cm-barcode i {
width: 2px;
background: #fff;
height: 100%;
}
.cm-barcode i:nth-child(2n) { height: 74%; width: 1px; }
.cm-barcode i:nth-child(3n) { height: 88%; width: 3px; }
.cm-barcode i:nth-child(5n) { height: 64%; }
</style>

View File

@@ -0,0 +1,161 @@
<template>
<div class="cn-root">
<div v-reveal="'down'" class="cn-mast">
<div class="cn-mast-row">
<span class="cn-mast-side">VOL.1314</span>
<span class="cn-mast-title">囍事日报</span>
<span class="cn-mast-side">NO.520</span>
</div>
<div class="cn-mast-en">THE WEDDING TIMES</div>
<div class="cn-dateline">
<span>{{ date }}</span>
<span>{{ lunar }}</span>
<span>头版头条</span>
</div>
</div>
<div v-reveal="{ variant: 'scale', delay: 160 }" class="cn-photo">
<img :src="heroImg" class="cn-img" fetchpriority="high" decoding="async" alt="封面" />
<span class="cn-caption">本报讯两位新人于近日喜结连理资料图</span>
</div>
<div v-reveal="{ variant: 'up', delay: 260 }" class="cn-headline">
<span class="cn-head-main">{{ groom }} {{ bride }} 即将完婚</span>
<span class="cn-head-sub">亲友各界反响热烈 · 诚邀莅临见证</span>
</div>
<div v-reveal="{ variant: 'up', delay: 340 }" class="cn-cols" aria-hidden="true">
<p>本报讯经多年相识相知两位新人正式宣布喜讯婚礼各项筹备工作现已就绪宴席流程均已妥善安排</p>
<p>据悉当日将设签到迎宾结婚典礼与喜宴等环节主办方表示期待您的光临共同见证这一美好时刻</p>
</div>
</div>
</template>
<script setup>
/** 日报编辑封面:报头 + 日期栏 + 头版照片 + 大标题 + 双栏导语 */
defineProps({
heroImg: { type: String, default: '' },
groom: { type: String, default: '' },
bride: { type: String, default: '' },
date: { type: String, default: '' },
lunar: { type: String, default: '' },
})
</script>
<style scoped>
.cn-root {
width: 100%;
flex: 1 1 auto;
min-height: 100dvh;
display: flex;
flex-direction: column;
padding: max(18px, env(safe-area-inset-top)) 20px 26px;
background: var(--c-paper);
color: var(--c-ink);
font-family: var(--font-serif);
overflow: hidden;
}
.cn-mast {
text-align: center;
border-bottom: 3px double var(--c-ink);
padding-bottom: 8px;
}
.cn-mast-row {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 8px;
}
.cn-mast-side {
font-family: var(--font-display);
font-size: 9px;
letter-spacing: 0.18em;
color: var(--c-muted);
}
.cn-mast-title {
font-weight: 700;
font-size: clamp(30px, 9vw, 40px);
letter-spacing: 0.24em;
text-indent: 0.24em;
line-height: 1.2;
}
.cn-mast-en {
font-family: var(--font-display);
font-size: 9px;
letter-spacing: 0.5em;
color: var(--c-muted);
margin-top: 2px;
}
.cn-dateline {
display: flex;
justify-content: space-between;
border-top: 1px solid var(--c-ink);
margin-top: 6px;
padding-top: 5px;
font-size: 10px;
letter-spacing: 0.1em;
color: var(--c-ink-soft);
}
.cn-photo {
margin-top: 14px;
border: 1px solid var(--c-ink);
padding: 5px;
background: var(--c-card);
}
.cn-img {
width: 100%;
aspect-ratio: 4 / 3;
object-fit: cover;
display: block;
filter: grayscale(0.35) contrast(1.04);
}
.cn-caption {
display: block;
font-size: 9.5px;
letter-spacing: 0.06em;
color: var(--c-muted);
padding: 5px 2px 1px;
}
.cn-headline {
margin-top: 14px;
text-align: center;
display: flex;
flex-direction: column;
gap: 6px;
}
.cn-head-main {
font-weight: 700;
font-size: clamp(21px, 6.4vw, 27px);
letter-spacing: 0.08em;
line-height: 1.35;
}
.cn-head-sub {
font-size: 12px;
letter-spacing: 0.16em;
color: var(--c-ink-soft);
}
.cn-cols {
margin-top: 12px;
flex: 1;
min-height: 0;
column-count: 2;
column-gap: 16px;
column-rule: 1px solid rgba(var(--c-line-rgb), 0.5);
border-top: 1px solid rgba(var(--c-line-rgb), 0.6);
padding-top: 10px;
overflow: hidden;
}
.cn-cols p {
margin: 0 0 8px;
font-size: 11.5px;
line-height: 1.95;
letter-spacing: 0.04em;
text-align: justify;
color: var(--c-ink-soft);
}
.cn-cols p::first-letter {
font-size: 1.6em;
font-weight: 700;
color: var(--c-ink);
}
</style>

View File

@@ -0,0 +1,152 @@
<template>
<div class="cp-root">
<div v-reveal="'down'" class="cp-top">
<span class="cp-score">1UP · {{ groom }}</span>
<span class="cp-score">2UP · {{ bride }}</span>
</div>
<div v-reveal="{ variant: 'scale', delay: 140 }" class="cp-frame">
<div class="cp-photo">
<img :src="heroImg" class="cp-img" fetchpriority="high" decoding="async" alt="封面" />
</div>
<span class="cp-heart cp-heart-1" aria-hidden="true"></span>
<span class="cp-heart cp-heart-2" aria-hidden="true"></span>
</div>
<div v-reveal="{ variant: 'up', delay: 260 }" class="cp-title-wrap">
<span class="cp-kicker">WEDDING QUEST</span>
<span class="cp-names">{{ groom }} {{ bride }}</span>
<span class="cp-date">{{ date }}</span>
<span class="cp-date cp-lunar">{{ lunar }}</span>
</div>
<div v-reveal="{ variant: 'up', delay: 380 }" class="cp-start">
<span class="cp-start-text">- PRESS START -</span>
<span class="cp-hint">向上滑动开始我们的故事</span>
</div>
</div>
</template>
<script setup>
/** 复古像素封面游戏标题屏1UP/2UP、像素框照片、像素心、PRESS START */
defineProps({
heroImg: { type: String, default: '' },
groom: { type: String, default: '' },
bride: { type: String, default: '' },
date: { type: String, default: '' },
lunar: { type: String, default: '' },
})
</script>
<style scoped>
.cp-root {
width: 100%;
flex: 1 1 auto;
min-height: 100dvh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: max(20px, env(safe-area-inset-top)) 22px 30px;
background:
var(--t-bg-texture),
var(--c-bg);
font-family: var(--font-pixel);
color: var(--c-ink);
overflow: hidden;
}
.cp-top {
width: 100%;
display: flex;
justify-content: space-between;
font-size: 11px;
letter-spacing: 0.08em;
color: var(--c-line);
}
.cp-frame {
position: relative;
width: min(78%, 250px);
}
.cp-photo {
border: 4px solid var(--c-ink);
outline: 4px solid var(--c-primary);
outline-offset: 4px;
padding: 4px;
background: var(--c-card);
box-shadow: 8px 8px 0 rgba(var(--c-line-rgb), 0.4);
}
.cp-img {
width: 100%;
aspect-ratio: 3 / 4;
object-fit: cover;
display: block;
image-rendering: pixelated;
filter: saturate(1.25) contrast(1.05);
}
/* 像素心box-shadow 拼点阵) */
.cp-heart {
position: absolute;
width: 6px;
height: 6px;
background: transparent;
box-shadow:
6px 0 var(--c-primary), 12px 0 var(--c-primary), 24px 0 var(--c-primary), 30px 0 var(--c-primary),
0 6px var(--c-primary), 6px 6px var(--c-primary), 12px 6px var(--c-primary), 18px 6px var(--c-primary), 24px 6px var(--c-primary), 30px 6px var(--c-primary), 36px 6px var(--c-primary),
0 12px var(--c-primary), 6px 12px var(--c-primary), 12px 12px var(--c-primary), 18px 12px var(--c-primary), 24px 12px var(--c-primary), 30px 12px var(--c-primary), 36px 12px var(--c-primary),
6px 18px var(--c-primary), 12px 18px var(--c-primary), 18px 18px var(--c-primary), 24px 18px var(--c-primary), 30px 18px var(--c-primary),
12px 24px var(--c-primary), 18px 24px var(--c-primary), 24px 24px var(--c-primary),
18px 30px var(--c-primary);
animation: cpHeartBeat 1.4s steps(2) infinite;
}
.cp-heart-1 { top: -14px; left: -22px; transform: scale(0.6); }
.cp-heart-2 { bottom: -8px; right: -26px; transform: scale(0.42) rotate(12deg); }
@keyframes cpHeartBeat {
0%, 100% { opacity: 1; }
50% { opacity: 0.55; }
}
.cp-title-wrap {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
text-align: center;
}
.cp-kicker {
font-size: 10px;
letter-spacing: 0.3em;
color: var(--c-line);
}
.cp-names {
font-size: clamp(19px, 6vw, 24px);
letter-spacing: 0.06em;
color: var(--c-primary);
text-shadow: 3px 3px 0 rgba(var(--c-line-rgb), 0.45);
}
.cp-date {
font-size: 11px;
letter-spacing: 0.1em;
color: var(--c-ink-soft);
}
.cp-lunar { font-size: 10px; color: var(--c-muted); }
.cp-start {
display: flex;
flex-direction: column;
align-items: center;
gap: 7px;
}
.cp-start-text {
font-size: 13px;
letter-spacing: 0.14em;
color: var(--c-ink);
animation: cpBlink 1.1s steps(1) infinite;
}
@keyframes cpBlink {
0%, 60% { opacity: 1; }
61%, 100% { opacity: 0; }
}
.cp-hint {
font-size: 9px;
letter-spacing: 0.16em;
color: var(--c-muted);
}
</style>

View File

@@ -0,0 +1,102 @@
<template>
<div class="cz-root">
<div v-reveal="'down'" class="cz-kicker">WEDDING INVITATION</div>
<div class="cz-mid">
<div v-reveal="{ variant: 'scale', delay: 140 }" class="cz-photo">
<img :src="heroImg" class="cz-img" fetchpriority="high" decoding="async" alt="封面" />
</div>
<i v-reveal="{ variant: 'up', delay: 220 }" class="cz-axis" aria-hidden="true"></i>
<div v-reveal="{ variant: 'up', delay: 280 }" class="cz-names">
<span>{{ groom }}</span>
<em>/</em>
<span>{{ bride }}</span>
</div>
</div>
<div v-reveal="{ variant: 'up', delay: 360 }" class="cz-foot">
<span>{{ date }}</span>
<span class="cz-lunar">{{ lunar }}</span>
</div>
</div>
</template>
<script setup>
/** 极简主义封面:小图 + 一条轴线 + 细字排印,大量留白 */
defineProps({
heroImg: { type: String, default: '' },
groom: { type: String, default: '' },
bride: { type: String, default: '' },
date: { type: String, default: '' },
lunar: { type: String, default: '' },
})
</script>
<style scoped>
.cz-root {
width: 100%;
flex: 1 1 auto;
min-height: 100dvh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: max(34px, env(safe-area-inset-top)) 24px 44px;
background: var(--c-bg);
color: var(--c-ink);
font-family: var(--font-sans);
overflow: hidden;
}
.cz-kicker {
font-size: 9px;
letter-spacing: 0.66em;
text-indent: 0.66em;
color: var(--c-muted);
}
.cz-mid {
display: flex;
flex-direction: column;
align-items: center;
gap: 22px;
}
.cz-photo {
width: min(52vw, 190px);
aspect-ratio: 3 / 4;
overflow: hidden;
}
.cz-img {
width: 100%;
height: 100%;
object-fit: cover;
filter: grayscale(0.16);
}
.cz-axis {
width: 1px;
height: 34px;
background: rgba(var(--c-line-rgb), 0.7);
}
.cz-names {
display: flex;
align-items: baseline;
gap: 14px;
font-size: clamp(21px, 6.4vw, 26px);
font-weight: 300;
letter-spacing: 0.34em;
text-indent: 0.34em;
}
.cz-names em {
font-style: normal;
font-size: 0.6em;
color: var(--c-muted);
}
.cz-foot {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
font-size: 10px;
letter-spacing: 0.3em;
color: var(--c-muted);
}
.cz-lunar { font-size: 9px; opacity: 0.85; }
</style>

File diff suppressed because it is too large Load Diff