diff --git a/hunliji-api/hl-api b/hunliji-api/hl-api new file mode 100644 index 0000000..16cc154 Binary files /dev/null and b/hunliji-api/hl-api differ diff --git a/hunliji-api/main.go b/hunliji-api/main.go index bce2146..576981c 100644 --- a/hunliji-api/main.go +++ b/hunliji-api/main.go @@ -111,7 +111,7 @@ func requireAdmin(c *gin.Context) bool { } func initDB() { - dsn := "root:root@tcp(127.0.0.1:3306)/nl_wedding?charset=utf8mb4&parseTime=True&loc=Local" + dsn := "root:mysql_PKC65h@tcp(127.0.0.1:3306)/nl_wedding?charset=utf8mb4&parseTime=True&loc=Local" var err error db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { @@ -433,6 +433,6 @@ func main() { }) } - fmt.Println("婚礼纪后端 API 已在 http://localhost:8080 启动") - r.Run(":8080") + fmt.Println("婚礼纪后端 API 已在 http://localhost:15201 启动") + r.Run(":15201") } diff --git a/vite-tailwindcss/dist-verify/index.html b/vite-tailwindcss/dist-verify/index.html deleted file mode 100644 index 9b5342d..0000000 --- a/vite-tailwindcss/dist-verify/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - 婚礼请柬 · Wedding Invitation - - - - -
- - diff --git a/vite-tailwindcss/dist-verify/vite.svg b/vite-tailwindcss/dist-verify/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/vite-tailwindcss/dist-verify/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/vite-tailwindcss/dist.zip b/vite-tailwindcss/dist.zip new file mode 100644 index 0000000..2552495 Binary files /dev/null and b/vite-tailwindcss/dist.zip differ diff --git a/vite-tailwindcss/index.html b/vite-tailwindcss/index.html index ddc8fbf..8572ce5 100644 --- a/vite-tailwindcss/index.html +++ b/vite-tailwindcss/index.html @@ -1,10 +1,16 @@ - + - 婚礼请柬 · Wedding Invitation + + + + + + + 李琦&李逸烁的婚礼请柬
diff --git a/vite-tailwindcss/src/views/index/index.vue b/vite-tailwindcss/src/views/index/index.vue index 03caf16..b6c5d18 100644 --- a/vite-tailwindcss/src/views/index/index.vue +++ b/vite-tailwindcss/src/views/index/index.vue @@ -151,9 +151,31 @@ > {{ day }} @@ -167,22 +189,22 @@ -
-
-
- 婚礼流程 - Wedding Schedule +
+
+ 婚礼流程 + Wedding Schedule
-
-
-
-
-
- {{ item.time }} - {{ item.event }} - {{ item.desc }} +
+
+
{{ item.time }}
+
+ +
+
+ {{ item.event }} + {{ item.desc }}
@@ -338,7 +360,7 @@ const introExitClass = computed(() => { const effect = ['wind', 'book', 'lift', 'doors'].includes(data.value.introExitEffect) ? data.value.introExitEffect : 'wind' return `intro-exit-${effect}` }) -const introExitDuration = computed(() => ({ wind: 1280, book: 1220, lift: 980, doors: 1180 }[data.value.introExitEffect] || 1280)) +const introExitDuration = computed(() => ({ wind: 1280, book: 1680, lift: 980, doors: 1180 }[data.value.introExitEffect] || 1280)) const calendarWeekdays = ['一', '二', '三', '四', '五', '六', '日'] const monthNames = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'] @@ -659,6 +681,77 @@ onUnmounted(() => { font-family: var(--font-serif); } +/* ---------- 婚礼流程 ---------- */ +.schedule-page { + background: + linear-gradient(180deg, rgba(253,251,247,0.74), rgba(247,246,242,0.92)), + radial-gradient(circle at 50% 8%, rgba(232,201,210,0.14), transparent 34%); +} +.schedule-page::before, +.schedule-page::after { + content: ''; position: absolute; left: 50%; transform: translateX(-50%); + width: min(62vw, 230px); height: 1px; pointer-events: none; + background: linear-gradient(90deg, transparent, rgba(168,140,107,0.34), transparent); +} +.schedule-page::before { top: 42px; } +.schedule-page::after { bottom: 42px; } +.schedule-heading { + text-align: center; margin-bottom: 38px; position: relative; z-index: 1; +} +.schedule-title { + display: block; color: #a88c6b; font-size: 26px; line-height: 1.25; + letter-spacing: 0.28em; padding-left: 0.28em; font-weight: 400; +} +.schedule-kicker { + display: block; margin-top: 10px; color: #8A8680; font-size: 10px; + letter-spacing: 0.4em; padding-left: 0.4em; text-transform: uppercase; +} +.schedule-list { + width: min(100%, 360px); margin: 0 auto; position: relative; + display: flex; flex-direction: column; gap: 24px; +} +.schedule-list::before { + content: ''; position: absolute; top: 16px; bottom: 16px; left: 104px; + width: 1px; background: linear-gradient(180deg, transparent, rgba(168,140,107,0.54) 12%, rgba(168,140,107,0.54) 88%, transparent); +} +.schedule-row { + position: relative; display: grid; grid-template-columns: 78px 52px 1fr; + align-items: center; min-height: 68px; +} +.schedule-time { + justify-self: end; min-width: 72px; padding: 9px 10px 8px; + color: #8f7250; font-family: var(--font-number); font-size: 19px; + letter-spacing: 0.08em; text-align: center; + border-top: 1px solid rgba(168,140,107,0.28); + border-bottom: 1px solid rgba(168,140,107,0.2); + background: rgba(255,255,255,0.26); +} +.schedule-axis { + position: relative; height: 100%; display: flex; align-items: center; justify-content: center; +} +.schedule-node { + width: 18px; height: 18px; border-radius: 9999px; position: relative; + display: flex; align-items: center; justify-content: center; + background: #fbf7ef; border: 1px solid rgba(168,140,107,0.52); + box-shadow: 0 0 0 5px rgba(168,140,107,0.09), 0 6px 16px rgba(112,78,40,0.12); +} +.schedule-node i { + width: 6px; height: 6px; border-radius: 9999px; display: block; + background: #a88c6b; +} +.schedule-copy { + min-width: 0; padding: 13px 0 13px 2px; text-align: left; + border-bottom: 1px solid rgba(168,140,107,0.14); +} +.schedule-event { + display: block; color: #3f3428; font-family: var(--font-serif); + font-size: 16px; line-height: 1.4; letter-spacing: 0.16em; font-weight: 600; +} +.schedule-desc { + display: block; margin-top: 5px; color: #8A8680; font-size: 10px; + line-height: 1.5; letter-spacing: 0.2em; text-transform: uppercase; +} + /* ---------- 婚礼日历 ---------- */ .wedding-calendar-page { min-height: 76vh; @@ -711,35 +804,69 @@ onUnmounted(() => { } .calendar-day.is-empty { visibility: hidden; } .calendar-day-num { - position: relative; z-index: 2; + position: relative; z-index: 4; } .calendar-day.is-selected .calendar-day-num { - color: #8f4d5a; font-weight: 700; text-shadow: 0 1px 0 rgba(255,255,255,0.75); + width: 24px; height: 24px; border-radius: 9999px; + display: flex; align-items: center; justify-content: center; + color: #763342; font-weight: 900; font-size: 16px; + background: rgba(253,251,247,0.9); + box-shadow: 0 0 0 1px rgba(151,64,82,0.12), 0 4px 10px rgba(91,47,36,0.1); + text-shadow: 0 1px 0 rgba(255,255,255,0.82); } .heart-ring { position: absolute; inset: -9px; display: flex; align-items: center; justify-content: center; - z-index: 1; animation: heartBeat 1.65s ease-in-out infinite; - filter: drop-shadow(0 6px 10px rgba(151,76,91,0.18)); + z-index: 1; animation: heartBeat 1.8s ease-in-out infinite; + filter: drop-shadow(0 5px 9px rgba(110,38,48,0.16)); } .heart-ring svg { - width: 56px; height: 50px; overflow: visible; + width: 62px; height: 60px; overflow: visible; } .heart-brush { - fill: rgba(182,106,120,0.06); - stroke: #a94f62; - stroke-width: 4.2; + fill: none; + stroke: #8f354a; + stroke-width: 12.5; stroke-linecap: round; stroke-linejoin: round; - stroke-dasharray: 176; - stroke-dashoffset: 176; - animation: brushHeartDraw 1.25s cubic-bezier(0.18, 0.78, 0.24, 1) forwards; + stroke-dasharray: 310; + stroke-dashoffset: 310; + animation: brushHeartDraw 1.55s cubic-bezier(0.16, 0.82, 0.22, 1) forwards; } .heart-brush-shadow { - stroke: rgba(126,76,54,0.22); - stroke-width: 6; - transform: translate(1px, 1px) rotate(-2deg); + stroke: rgba(72,38,29,0.18); + stroke-width: 16; + transform: translate(2px, 3px) rotate(-2.2deg); animation-delay: .06s; } +.heart-brush-main { + stroke: #91364a; +} +.heart-brush-tail { + stroke: rgba(126,42,58,0.9); + stroke-width: 7.8; + stroke-dasharray: 58; + stroke-dashoffset: 58; + animation: brushTailDraw .62s cubic-bezier(0.18, 0.78, 0.24, 1) 1.08s forwards; +} +.heart-brush-cuts { + opacity: 0; + animation: dryBrushFlicker .42s ease-out .88s forwards; +} +.heart-brush-cuts path { + fill: none; + stroke: rgba(253,251,247,0.82); + stroke-width: 2.3; + stroke-linecap: round; + stroke-dasharray: 13 9; +} +.heart-brush-cuts path:nth-child(2) { stroke-width: 3; } +.heart-brush-cuts path:nth-child(3) { stroke-width: 2; opacity: .9; } +.heart-brush-cuts path:nth-child(4) { stroke-width: 1.8; opacity: .74; } +.heart-brush-speckles { + fill: rgba(120,42,56,0.56); + opacity: 0; + animation: inkDotIn .42s ease-out .72s forwards; +} .calendar-note { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 24px; color: #806f5c; font-family: var(--font-kai); @@ -803,14 +930,30 @@ onUnmounted(() => { animation: inviteWindExit 1180ms cubic-bezier(0.4, 0, 1, 1) forwards; } .curtain-root.is-opening.intro-exit-book .curtain-emblem { - opacity: 1; transform: none; + opacity: 1; transform: none; perspective: 1500px; } -.curtain-root.is-opening.intro-exit-book .emblem-inner { animation: inviteContentExit 480ms cubic-bezier(0.4, 0, 1, 1) 70ms forwards; } +.curtain-root.is-opening.intro-exit-book .curtain-bg, +.curtain-root.is-opening.intro-exit-book .curtain-veil, +.curtain-root.is-opening.intro-exit-book .curtain-door { + animation: bookBackdropFade 280ms ease-out forwards; +} +.curtain-root.is-opening.intro-exit-book .curtain-door-left, +.curtain-root.is-opening.intro-exit-book .curtain-door-right { + transform: none; +} +.curtain-root.is-opening.intro-exit-book .emblem-inner { animation: inviteContentExit 440ms cubic-bezier(0.4, 0, 1, 1) 330ms forwards; } .curtain-root.is-opening.intro-exit-book .invite-cover { transform-style: preserve-3d; - transform-origin: 0% 50%; - will-change: transform, opacity, filter; - animation: inviteBookExit 1120ms cubic-bezier(0.4, 0, 1, 1) forwards; + transform-origin: 0% 0%; + backface-visibility: hidden; + will-change: transform, opacity, filter, box-shadow; + animation: inviteBookExit 1220ms cubic-bezier(0.4, 0, 1, 1) 280ms forwards; +} +.curtain-root.is-opening.intro-exit-book .invite-cover::before { + animation: bookCurlShadow 1220ms cubic-bezier(0.4, 0, 1, 1) 280ms forwards; +} +.curtain-root.is-opening.intro-exit-book .invite-cover::after { + animation: bookCornerCurl 1220ms cubic-bezier(0.4, 0, 1, 1) 280ms forwards; } .curtain-root.is-opening.intro-exit-lift .curtain-emblem { opacity: 1; transform: none; @@ -1068,14 +1211,30 @@ onUnmounted(() => { 52% { transform: scale(1.1); } } @keyframes brushHeartDraw { - 0% { stroke-dashoffset: 176; opacity: .34; } - 66% { stroke-dashoffset: 0; opacity: 1; } + 0% { stroke-dashoffset: 310; opacity: .2; } + 70% { stroke-dashoffset: 0; opacity: 1; } 100% { stroke-dashoffset: 0; opacity: 1; } } +@keyframes brushTailDraw { + from { stroke-dashoffset: 58; opacity: .1; } + to { stroke-dashoffset: 0; opacity: .9; } +} +@keyframes dryBrushFlicker { + 0% { opacity: 0; transform: scale(.98); } + 100% { opacity: 1; transform: scale(1); } +} +@keyframes inkDotIn { + from { opacity: 0; transform: scale(.4); } + to { opacity: 1; transform: scale(1); } +} @keyframes veilFade { from { opacity: 1; } to { opacity: 0; } } +@keyframes bookBackdropFade { + 0% { opacity: 1; filter: blur(0); } + 100% { opacity: 0; filter: blur(2px); } +} @keyframes inviteContentExit { 0% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); } 100% { opacity: 0; transform: translateY(-7px) scale(.975); filter: blur(1px); } @@ -1088,11 +1247,82 @@ onUnmounted(() => { 100% { opacity: 0; transform: translate3d(96vw, -42vh, 0) rotate(24deg) scale(.82); filter: blur(2px); } } @keyframes inviteBookExit { - 0% { opacity: 1; transform: rotateY(0deg) translateX(0) translateZ(0) scale(1); filter: brightness(1); } - 9% { opacity: 1; transform: rotateY(0deg) translateX(7px) translateZ(0) scale(.985); filter: brightness(.98); } - 38% { opacity: 1; transform: rotateY(-42deg) translateX(-10px) translateZ(36px) scale(.975); filter: brightness(.94); } - 72% { opacity: .72; transform: rotateY(-88deg) translateX(-34px) translateZ(26px) scale(.95); filter: brightness(.9) blur(.4px); } - 100% { opacity: 0; transform: rotateY(-112deg) translateX(-70px) translateZ(0) scale(.9); filter: brightness(.85) blur(1.8px); } + 0% { + opacity: 1; + transform: translate3d(0, 0, 0) rotateX(0deg) rotateY(0deg) rotateZ(0deg) skew(0deg) scale(1); + filter: brightness(1) blur(0); + box-shadow: 0 28px 70px rgba(59,39,22,0.24), inset 0 0 0 10px rgba(255,255,255,0.34), inset 0 0 0 11px rgba(168,140,107,0.14); + } + 10% { + opacity: 1; + transform: translate3d(4px, 5px, 0) rotateX(0deg) rotateY(0deg) rotateZ(.4deg) skew(.2deg) scale(.982, .992); + filter: brightness(.98) blur(0); + } + 24% { + opacity: 1; + transform: translate3d(-10px, -14px, 42px) rotateX(-12deg) rotateY(18deg) rotateZ(-2deg) skew(1.2deg) scale(.992); + filter: brightness(1.04) blur(0); + box-shadow: 22px 30px 58px rgba(59,39,22,0.22), inset 14px 14px 24px rgba(87,57,31,0.1), inset 0 0 0 11px rgba(168,140,107,0.13); + } + 48% { + opacity: .96; + transform: translate3d(-60px, -66px, 86px) rotateX(-32deg) rotateY(56deg) rotateZ(-8deg) skew(2.6deg) scale(.965); + filter: brightness(.96) blur(.15px); + box-shadow: 44px 42px 66px rgba(59,39,22,0.27), inset 28px 24px 36px rgba(87,57,31,0.18), inset 0 0 0 11px rgba(168,140,107,0.1); + } + 74% { + opacity: .58; + transform: translate3d(-128px, -136px, 48px) rotateX(-48deg) rotateY(96deg) rotateZ(-15deg) skew(3.8deg) scale(.91); + filter: brightness(.88) blur(.7px); + } + 100% { + opacity: 0; + transform: translate3d(-214px, -226px, -18px) rotateX(-60deg) rotateY(122deg) rotateZ(-22deg) skew(4.2deg) scale(.84); + filter: brightness(.82) blur(1.8px); + box-shadow: 56px 30px 44px rgba(59,39,22,0.1), inset 32px 32px 38px rgba(87,57,31,0.22); + } +} +@keyframes bookCurlShadow { + 0%, 12% { + border-color: rgba(168,140,107,0.25); + box-shadow: none; + } + 34% { + border-color: rgba(168,140,107,0.2); + box-shadow: inset 18px 16px 24px rgba(79,51,28,0.14), inset -8px 0 18px rgba(255,255,255,0.48); + } + 72%, 100% { + border-color: rgba(168,140,107,0.08); + box-shadow: inset 28px 30px 38px rgba(79,51,28,0.18); + } +} +@keyframes bookCornerCurl { + 0% { + opacity: .44; + clip-path: polygon(0 0, 0 0, 0 0); + background: + radial-gradient(circle at 0 0, rgba(255,255,255,0.9), rgba(236,219,198,0.5) 34%, rgba(93,58,32,0.22) 58%, transparent 62%), + linear-gradient(135deg, rgba(168,140,107,0.15) 0 1px, transparent 2px); + } + 22% { + opacity: .96; + clip-path: polygon(0 0, 42% 0, 0 42%); + background: + radial-gradient(circle at 14% 14%, rgba(255,255,255,0.94), rgba(239,223,204,0.62) 34%, rgba(99,62,34,0.26) 60%, transparent 64%), + linear-gradient(135deg, rgba(255,255,255,0.42) 0 28%, rgba(92,58,31,0.2) 48%, transparent 57%); + } + 52% { + opacity: .82; + clip-path: polygon(0 0, 64% 0, 0 64%); + background: + radial-gradient(circle at 24% 24%, rgba(255,255,255,0.78), rgba(239,223,204,0.56) 32%, rgba(84,50,28,0.34) 60%, transparent 65%), + linear-gradient(132deg, rgba(255,255,255,0.34), rgba(83,49,27,0.25) 50%, transparent 60%); + } + 100% { + opacity: .18; + clip-path: polygon(0 0, 82% 0, 0 82%); + background: linear-gradient(132deg, rgba(255,255,255,0.28), rgba(72,45,26,0.32)); + } } @keyframes inviteLiftExit { 0% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }