Files
mwy/frontend/src/components/ReconcilePage.vue
flowerstonezl 3f84ad1891 mwy quanji
2026-05-21 15:30:57 +08:00

198 lines
7.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { usePreferredReducedMotion } from '@vueuse/core'
import { computed, ref } from 'vue'
import type { Memory } from '../api/client'
import { getStandardNepalTheme } from '../constants/nepalThemes'
import PolaroidCard from './PolaroidCard.vue'
import { renderMarkdown } from '../utils/renderMarkdown'
const props = defineProps<{
memory: Memory
}>()
const bodyHtml = computed(() => renderMarkdown(props.memory.main_text))
const theme = computed(() => getStandardNepalTheme(props.memory.nepal_art_style))
const reduceMotion = usePreferredReducedMotion()
const talkedItOut = ref(false)
</script>
<template>
<div
class="relative mx-auto max-w-lg overflow-hidden rounded-3xl bg-gradient-to-br px-3 pb-8 pt-6 sm:px-5 sm:pb-10 sm:pt-8"
:class="theme.gradient"
>
<div
class="pointer-events-none absolute -left-10 top-12 h-44 w-44 rounded-full bg-emerald-300/22 blur-[3rem]"
aria-hidden="true"
/>
<div
class="pointer-events-none absolute -right-10 bottom-10 h-52 w-52 rounded-full bg-cyan-300/18 blur-[3.5rem]"
aria-hidden="true"
/>
<div
class="relative z-[1] mx-auto mb-7 max-w-[min(100%,396px)] overflow-hidden rounded-[2rem] border border-emerald-200/65 bg-[linear-gradient(180deg,#f7fffb_0%,#eefcf7_100%)] shadow-[0_24px_56px_-18px_rgba(16,185,129,0.22)]"
>
<div class="pointer-events-none absolute inset-0 nepal-fiber opacity-[0.14] mix-blend-multiply" />
<div class="relative px-5 pb-5 pt-5 sm:px-6 sm:pb-6">
<div class="flex items-start justify-between gap-4">
<div>
<p class="text-[10px] font-semibold uppercase tracking-[0.32em] text-emerald-700/65">
Make Up / 05.04
</p>
<h3 class="mt-2 font-display-cn text-[1.9rem] leading-none text-emerald-950">
和好了在一起吧
</h3>
</div>
<div
class="rounded-2xl border border-emerald-200/70 bg-white/88 px-3 py-2 text-right shadow-[0_8px_20px_rgba(16,185,129,0.12)]"
>
<p class="text-[9px] font-semibold tracking-[0.22em] text-emerald-700/70">
关系状态
</p>
<p class="mt-1 font-brush text-xl text-emerald-950">已和好</p>
</div>
</div>
<div class="mt-6 rounded-[1.8rem] border border-emerald-200/60 bg-white/78 p-4 shadow-inner">
<div class="grid gap-3 sm:grid-cols-[0.92fr_0.16fr_0.92fr] sm:items-center">
<div
class="rounded-[1.5rem] border border-rose-200/65 bg-rose-50/88 px-4 py-4 shadow-[0_10px_20px_rgba(244,114,182,0.08)]"
:class="[
reduceMotion === 'reduce' ? '' : 'reconcile-card-left',
talkedItOut ? 'sm:translate-x-2' : '',
]"
>
<p class="text-[10px] font-semibold uppercase tracking-[0.25em] text-rose-700/65">
Before
</p>
<p class="mt-2 text-lg font-medium text-rose-950">别扭沉默想解释</p>
</div>
<div class="relative flex items-center justify-center py-2">
<div
class="flex h-16 w-16 items-center justify-center rounded-full bg-gradient-to-br from-emerald-300 to-cyan-300 text-2xl text-white shadow-[0_14px_28px_rgba(16,185,129,0.22)]"
:class="[
reduceMotion === 'reduce' ? '' : 'reconcile-heartbeat',
talkedItOut ? 'scale-110' : '',
]"
role="button"
tabindex="0"
@click="talkedItOut = !talkedItOut"
>
</div>
<div class="absolute inset-x-0 top-1/2 h-px -translate-y-1/2 bg-gradient-to-r from-rose-200 via-emerald-300 to-cyan-200" aria-hidden="true" />
</div>
<div
class="rounded-[1.5rem] border border-cyan-200/70 bg-cyan-50/88 px-4 py-4 shadow-[0_10px_20px_rgba(34,211,238,0.08)]"
:class="[
reduceMotion === 'reduce' ? '' : 'reconcile-card-right',
talkedItOut ? 'sm:-translate-x-2' : '',
]"
>
<p class="text-[10px] font-semibold uppercase tracking-[0.25em] text-cyan-700/65">
After
</p>
<p class="mt-2 text-lg font-medium text-cyan-950">说开了靠近了在一起了</p>
</div>
</div>
<div class="mt-4 rounded-[1.4rem] border border-emerald-200/75 bg-emerald-50/85 px-4 py-4">
<div class="flex flex-wrap justify-center gap-2">
<span
v-for="tag in ['把话说完', '空气变甜', '正式在一起']"
:key="tag"
class="rounded-full border border-emerald-200 bg-white/85 px-3 py-1.5 text-[11px] font-medium text-emerald-800/85"
>
{{ tag }}
</span>
</div>
</div>
<div class="mt-4 flex flex-col items-center gap-2">
<button
type="button"
class="rounded-full border border-emerald-200 bg-white/92 px-4 py-2 text-xs font-semibold tracking-[0.18em] text-emerald-900 transition hover:bg-emerald-50"
@click="talkedItOut = !talkedItOut"
>
{{ talkedItOut ? '先把话收回一点' : '把话说开' }}
</button>
<p class="text-center text-[11px] leading-relaxed text-emerald-900/70">
{{ talkedItOut ? '说开以后,卡在中间的那口气终于顺了。' : '轻点一下让“Before”和“After”靠近一点。' }}
</p>
</div>
</div>
</div>
</div>
<div class="relative z-[1] flex flex-col gap-6 sm:gap-8">
<PolaroidCard :memory="memory" :index="memory.story_order" compact />
<div
class="nepal-torn-panel mx-auto max-w-md border border-emerald-200/70 bg-gradient-to-b from-[#fffefa] to-emerald-50/65 px-5 py-6 shadow-[0_16px_36px_-12px_rgba(16,185,129,0.18)] ring-1 ring-white/80 sm:px-6 sm:py-7"
>
<div class="mb-4 h-1 w-14 rounded-full bg-gradient-to-r from-emerald-400 to-cyan-400" aria-hidden="true" />
<div
class="text-[15px] leading-[1.82] tracking-wide text-emerald-950/88 [&_a]:font-bold [&_a]:text-cyan-700 [&_a]:underline [&_a]:underline-offset-4 [&_blockquote]:border-l-4 [&_blockquote]:border-emerald-300/60 [&_blockquote]:bg-emerald-50/55 [&_blockquote]:py-1 [&_blockquote]:pl-3 [&_blockquote]:text-emerald-900/70 [&_code]:rounded [&_code]:bg-emerald-100/50 [&_code]:px-1.5 [&_strong]:text-emerald-950 [&_p+p]:mt-4"
v-html="bodyHtml"
/>
</div>
</div>
</div>
</template>
<style scoped>
.reconcile-heartbeat {
animation: reconcile-heartbeat 2.4s ease-in-out infinite;
}
@keyframes reconcile-heartbeat {
0%,
100% {
transform: scale(1);
}
20% {
transform: scale(1.08);
}
36% {
transform: scale(0.98);
}
56% {
transform: scale(1.05);
}
}
.reconcile-card-left {
animation: reconcile-card-left 0.65s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.reconcile-card-right {
animation: reconcile-card-right 0.65s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes reconcile-card-left {
0% {
opacity: 0;
transform: translateX(-16px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
@keyframes reconcile-card-right {
0% {
opacity: 0;
transform: translateX(16px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
</style>