Files
Starlight_Launcher/apps/app-frontend/src/components/ui/skin-site/wiki/WikiAttachmentNode.vue
T
AxTps 71b8d111fb
Sync source to CNB / Sync Git ref (push) Skipped
feat: 新增皮肤站维基只读浏览页
- 新增 WikiView 页面:输入标题加载页面,支持内部词条跳转与返回栈
- 新增 WikiNodeRenderer 递归渲染器:标题、段落、加粗斜体下划线删除线、高亮、行内代码、黑幕、分隔线、内外链、有序无序列表、引用、代码块、表格、附件、提示块
- 新增 WikiNotice 提示块与 WikiAttachmentNode 附件组件,图片支持点击查看大图
- 补充维基节点与附件类型定义,新增附件查询接口与附件内容 URL 拼接
- 主页导航 Wiki 卡片改为站内打开
- 中英文各补 10 个文案
2026-10-18 13:13:03 +08:00

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>