Files
tianshu-engine/src/components/ChapterSelect.vue

152 lines
2.9 KiB
Vue

<script setup lang="ts">
import type { ChapterInfo } from '@engine/types'
defineProps<{
chapters: ChapterInfo[]
unlockedIds: Set<string>
}>()
const emit = defineEmits<{
select: [chapterId: string]
back: []
}>()
</script>
<template>
<div class="chapter-overlay">
<div class="chapter-panel">
<h2 class="chapter-title">章节选择</h2>
<div class="chapter-grid">
<div
v-for="ch in chapters"
:key="ch.id"
class="chapter-card"
:class="{ locked: !unlockedIds.has(ch.id) }"
@click="unlockedIds.has(ch.id) && emit('select', ch.id)"
>
<div class="chapter-thumb">
<img v-if="ch.thumbnail" :src="ch.thumbnail" class="thumb-img" />
<div v-else class="thumb-placeholder">?</div>
</div>
<div class="chapter-label">{{ ch.label }}</div>
<div v-if="!unlockedIds.has(ch.id)" class="lock-icon">🔒</div>
</div>
</div>
<button class="back-btn" @click="emit('back')">返回</button>
</div>
</div>
</template>
<style scoped>
.chapter-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.88);
display: flex;
align-items: center;
justify-content: center;
z-index: 200;
}
.chapter-panel {
background: #1a1a2e;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 10px;
padding: 36px 40px;
min-width: 520px;
max-width: 700px;
}
.chapter-title {
text-align: center;
font-size: 22px;
font-weight: 400;
color: #ddd;
letter-spacing: 3px;
margin-bottom: 28px;
}
.chapter-grid {
display: flex;
gap: 16px;
justify-content: center;
}
.chapter-card {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
padding: 16px;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
cursor: pointer;
transition: background 0.2s, border-color 0.2s, transform 0.15s;
width: 150px;
}
.chapter-card:hover:not(.locked) {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(255, 255, 255, 0.25);
transform: translateY(-2px);
}
.chapter-card.locked {
opacity: 0.4;
cursor: default;
}
.chapter-thumb {
width: 100px;
height: 56px;
background: rgba(0, 0, 0, 0.4);
border-radius: 4px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.thumb-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.thumb-placeholder {
font-size: 24px;
color: #555;
}
.chapter-label {
font-size: 13px;
color: #ccc;
text-align: center;
}
.lock-icon {
font-size: 14px;
}
.back-btn {
display: block;
margin: 24px auto 0;
padding: 10px 36px;
font-size: 14px;
color: #888;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 4px;
cursor: pointer;
transition: background 0.15s, color 0.15s;
}
.back-btn:hover {
background: rgba(255, 255, 255, 0.1);
color: #ccc;
}
</style>