Files
NovalRedot/frontend/src/views/NovelWorkspace.vue

92 lines
2.2 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 { ref, onMounted, provide } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { fetchNovel } from '@/api/novels'
import { useToast } from '@/composables/useToast'
import type { Novel } from '@/types/novel'
import NovelSubNav from '@/components/novel/NovelSubNav.vue'
const route = useRoute()
const router = useRouter()
const toast = useToast()
const novelId = Number(route.params.id)
const novel = ref<Novel | null>(null)
const loading = ref(true)
/** 子页面可设置的副标题(如 "共 5 个节点" */
const subtitle = ref('')
async function load() {
loading.value = true
try {
novel.value = await fetchNovel(novelId)
} catch {
toast.error('作品不存在')
router.push({ name: 'home' })
} finally {
loading.value = false
}
}
// 提供给子路由
provide('workspace-novel', novel)
provide('workspace-novel-id', novelId)
provide('workspace-subtitle', subtitle)
onMounted(load)
</script>
<template>
<div v-if="!loading && novel" class="workspace">
<NovelSubNav
:novel-id="novelId"
:novel-title="novel.title"
:subtitle="subtitle"
>
<template #actions>
<!-- 子页面通过 Teleport 注入操作按钮 -->
<div id="workspace-actions" />
</template>
</NovelSubNav>
<div class="workspace-content">
<RouterView />
</div>
</div>
<div v-else-if="loading" class="workspace-loading">
<div class="loading-pulse" style="height: 1.5rem; width: 30%; margin-bottom: var(--space-md)" />
<div class="loading-pulse" style="height: 1rem; width: 60%; margin-bottom: var(--space-2xl)" />
<div class="loading-pulse" style="height: 20rem; width: 100%" />
</div>
</template>
<style scoped>
.workspace {
max-width: 900px;
margin: 0 auto;
}
.workspace-content {
animation: fadeInUp var(--duration-normal) var(--ease-out-smooth) both;
}
.workspace-loading {
max-width: 900px;
margin: var(--space-3xl) auto;
}
.loading-pulse {
background: linear-gradient(
90deg,
var(--paper-100) 25%,
var(--paper-200) 50%,
var(--paper-100) 75%
);
background-size: 200% 100%;
border-radius: var(--radius-sm);
animation: shimmer 1.5s ease infinite;
}
</style>