Sync source to CNB / Sync Git ref (push) Skipped
- 新增 WikiView 页面:输入标题加载页面,支持内部词条跳转与返回栈 - 新增 WikiNodeRenderer 递归渲染器:标题、段落、加粗斜体下划线删除线、高亮、行内代码、黑幕、分隔线、内外链、有序无序列表、引用、代码块、表格、附件、提示块 - 新增 WikiNotice 提示块与 WikiAttachmentNode 附件组件,图片支持点击查看大图 - 补充维基节点与附件类型定义,新增附件查询接口与附件内容 URL 拼接 - 主页导航 Wiki 卡片改为站内打开 - 中英文各补 10 个文案
75 lines
2.1 KiB
Vue
75 lines
2.1 KiB
Vue
<script setup lang="ts">
|
|
import { computed, onMounted, ref } from 'vue'
|
|
|
|
import {
|
|
type SkinSiteWikiAttachmentInfo,
|
|
skinSiteWikiAttachment,
|
|
skinSiteWikiAttachmentUrl,
|
|
} from '@/helpers/skin-site-api'
|
|
|
|
const props = defineProps<{ name: string; caption?: string | null }>()
|
|
|
|
const attachment = ref<SkinSiteWikiAttachmentInfo | null>(null)
|
|
const loading = ref(true)
|
|
const viewerOpen = ref(false)
|
|
|
|
const contentUrl = computed(() =>
|
|
attachment.value ? skinSiteWikiAttachmentUrl(attachment.value.id) : '#',
|
|
)
|
|
const imageCaption = computed(() => {
|
|
const caption = props.caption?.trim() ?? ''
|
|
return caption === props.name || caption === attachment.value?.name ? '' : caption
|
|
})
|
|
|
|
onMounted(async () => {
|
|
try {
|
|
const res = await skinSiteWikiAttachment(props.name)
|
|
if (res.success) attachment.value = res.payload
|
|
} catch {
|
|
// ignore
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<span
|
|
v-if="loading"
|
|
class="inline-flex min-h-20 min-w-32 items-center justify-center rounded-lg border border-solid border-surface-5"
|
|
>
|
|
<span class="text-xs text-secondary">…</span>
|
|
</span>
|
|
<figure v-else-if="attachment?.image" class="my-5 inline-block max-w-full">
|
|
<button type="button" class="block max-w-full cursor-zoom-in rounded-lg" @click="viewerOpen = true">
|
|
<img
|
|
class="max-h-[70vh] max-w-full rounded-lg border border-solid border-surface-5 object-contain shadow-md"
|
|
:src="contentUrl"
|
|
:alt="caption || attachment.name"
|
|
loading="lazy"
|
|
decoding="async"
|
|
/>
|
|
</button>
|
|
<figcaption v-if="imageCaption" class="mt-2 text-center text-sm text-secondary">
|
|
{{ imageCaption }}
|
|
</figcaption>
|
|
</figure>
|
|
<a
|
|
v-else-if="attachment"
|
|
class="inline-flex items-center gap-1 text-brand underline-offset-2 hover:underline"
|
|
:href="contentUrl"
|
|
download
|
|
>
|
|
{{ caption || attachment.name }}
|
|
</a>
|
|
<span v-else class="text-red">附件“{{ name }}”不存在</span>
|
|
|
|
<div
|
|
v-if="viewerOpen"
|
|
class="fixed inset-0 z-[60] flex items-center justify-center bg-black/80 p-4"
|
|
@click.self="viewerOpen = false"
|
|
>
|
|
<img :src="contentUrl" :alt="caption || attachment?.name" class="max-h-[92vh] max-w-[92vw] object-contain" />
|
|
</div>
|
|
</template>
|