|
- <template>
- <div class="min-h-screen bg-[var(--c-f3f7fb)]">
- <AppHero :kicker="kicker" :title="title" :desc="updatedText" />
-
- <main class="mx-auto max-w-4xl px-4 py-7 sm:px-6 lg:py-10">
- <article class="rounded-3xl border border-[var(--c-e7eef7)] bg-[var(--c-ffffff)] p-6 shadow-[0_16px_40px_var(--sh-34-68-112-60)] lg:p-10">
- <!-- 正文由后台维护,服务端渲染,内容缺失时给明确空态而不是白屏 -->
- <div v-if="content" class="legal-body" v-html="content" />
- <div v-else class="py-16 text-center">
- <UIcon name="i-lucide-file-text" class="mx-auto mb-4 size-10 text-[var(--c-a0aabb)]" />
- <div class="text-base font-extrabold text-[var(--c-172033)]">内容暂未发布</div>
- <p class="mx-auto mt-2 max-w-md text-sm leading-6 text-[var(--c-8a97a8)]">
- 该内容正在整理中,如需了解详情可通过页脚的联系方式与我们沟通。
- </p>
- <NuxtLink
- to="/"
- class="mt-6 inline-flex h-10 cursor-pointer items-center rounded-full bg-[var(--c-eef7ff)] px-6 text-sm font-bold text-[var(--c-0b8cff)] transition-colors hover:bg-[var(--c-e0f0ff)]"
- >
- 返回首页
- </NuxtLink>
- </div>
- </article>
- </main>
- </div>
- </template>
-
- <script setup>
- import dayjs from 'dayjs'
- import { cleanRichText } from '~/utils/richtext'
-
- const props = defineProps({
- /** html 表里的 key:service / privacy */
- docKey: { type: String, required: true },
- fallbackTitle: { type: String, default: '' },
- kicker: { type: String, default: 'LEGAL' },
- })
-
- const { post } = useApi()
-
- /*
- SSR 取正文:协议页要能被搜索引擎抓到。
- 清洗放在 transform 里,这样 Nuxt payload 里只带清洗后的正文——
- 否则原始 Word 正文(3 万多字、带满内联样式)会被序列化进页面,白白多传一份。
- */
- const { data } = await useAsyncData(
- () => `legal-${props.docKey}`,
- () => post('/common/gethtml', { key: props.docKey }).catch(() => ({ data: {} })),
- {
- transform: (res) => {
- const doc = res?.data || {}
- return {
- title: doc.title || '',
- content: cleanRichText(doc.content || ''),
- update_time: doc.update_time || '',
- }
- },
- },
- )
-
- const title = computed(() => data.value?.title || props.fallbackTitle)
- const content = computed(() => data.value?.content || '')
- const updatedText = computed(() => {
- const time = data.value?.update_time
- if (!time) return ''
- return `最近更新:${dayjs(time).format('YYYY-MM-DD')}`
- })
- </script>
-
- <style scoped>
- /*
- 正文来自后台富文本,用 :deep 统一排版;
- 颜色走主题变量,暗色模式下同样可读。
- */
- .legal-body {
- color: var(--c-4b5b70);
- font-size: 15px;
- line-height: 1.85;
- word-break: break-word;
- }
- .legal-body :deep(h1),
- .legal-body :deep(h2),
- .legal-body :deep(h3),
- .legal-body :deep(h4) {
- margin: 1.6em 0 0.7em;
- color: var(--c-172033);
- font-weight: 800;
- line-height: 1.4;
- }
- .legal-body :deep(h1) { font-size: 22px; }
- .legal-body :deep(h2) { font-size: 19px; }
- .legal-body :deep(h3) { font-size: 17px; }
- .legal-body :deep(h4) { font-size: 15px; }
- /* Word 导出的正文里 p / div / span 用得很随意,这里统一接管排版 */
- .legal-body :deep(p) { margin: 0 0 0.9em; padding: 0; }
- .legal-body :deep(p:last-child) { margin-bottom: 0; }
- .legal-body :deep(div) { line-height: 1.85; }
- .legal-body :deep(span) { font-size: inherit; line-height: inherit; color: inherit; }
- .legal-body :deep(strong),
- .legal-body :deep(b) { color: var(--c-172033); font-weight: 700; }
- /* Tailwind preflight 会清掉列表符号与缩进,这里补回来 */
- .legal-body :deep(ul),
- .legal-body :deep(ol) { margin: 0.9em 0; padding-left: 1.6em; }
- .legal-body :deep(ul) { list-style: disc outside; }
- .legal-body :deep(ol) { list-style: decimal outside; }
- .legal-body :deep(ul ul) { list-style: circle outside; }
- .legal-body :deep(li) { margin: 0.35em 0; padding: 0; line-height: 1.8; }
- .legal-body :deep(li > p) { margin: 0; }
- .legal-body :deep(a) { color: var(--c-0b8cff); text-decoration: underline; }
- .legal-body :deep(img) { max-width: 100%; height: auto; border-radius: 12px; }
- .legal-body :deep(table) {
- width: 100%;
- margin: 1.2em 0;
- border-collapse: collapse;
- font-size: 14px;
- }
- .legal-body :deep(th),
- .legal-body :deep(td) {
- padding: 8px 10px;
- border: 1px solid var(--c-e7eef7);
- text-align: left;
- }
- .legal-body :deep(th) { background: var(--c-f7f9fd); color: var(--c-172033); font-weight: 700; }
- .legal-body :deep(hr) { margin: 1.6em 0; border: 0; border-top: 1px solid var(--c-eef2f7); }
- </style>
|