feat: main menu component, roadmap update

This commit is contained in:
2026-06-09 20:15:46 +08:00
parent 48da959b3a
commit 87ba62b9ef
3 changed files with 170 additions and 130 deletions

View File

@@ -8,7 +8,7 @@ import HotspotLayer from '@/components/HotspotLayer.vue'
import SaveLoadMenu from '@/components/SaveLoadMenu.vue'
import ChapterSelect from '@/components/ChapterSelect.vue'
import PlaybackBar from '@/components/PlaybackBar.vue'
import LangSwitch from '@/components/LangSwitch.vue'
import MainMenu from '@/components/MainMenu.vue'
import AchievementToast from '@/components/AchievementToast.vue'
import AchievementPanel from '@/components/AchievementPanel.vue'
import EndingGallery from '@/components/EndingGallery.vue'
@@ -238,21 +238,20 @@ init()
<button class="top-btn" @click="store.setShowSettings(true)">设置</button>
</div>
</div>
<div v-if="!started" class="start-overlay">
<LangSwitch />
<button class="start-btn" @click="handleStart">{{ t('ui.start') }}</button>
<button v-if="hasAutoSave" class="start-btn resume-btn" @click="handleResume">{{ t('ui.resume') }}</button>
<button v-if="store.chapters.length > 0" class="start-btn chapters-btn" @click="openChapterSelect">{{ t('ui.chapters') }}</button>
<button v-if="store.achievementDefs.length > 0" class="start-btn achievement-btn" @click="showAchievements = true">成就</button>
<button v-if="store.endings.length > 0" class="start-btn gallery-btn" @click="showEndingGallery = true">画廊</button>
<button class="start-btn settings-btn" @click="store.setShowSettings(true)">设置</button>
</div>
<div v-if="store.gameEnded" class="game-end-overlay">
<div class="game-end-text">{{ t('ui.gameEnd') }}</div>
<div v-if="store.chapters.length > 0" class="game-end-actions">
<button class="end-btn" @click="openChapterSelect">{{ t('ui.chapters') }}</button>
</div>
</div>
<MainMenu
v-if="!started || store.gameEnded"
:show-resume="!store.gameEnded && hasAutoSave"
:show-chapters="store.chapters.length > 0"
:show-achievements="store.achievementDefs.length > 0"
:show-gallery="store.endings.length > 0"
:is-game-end="store.gameEnded"
@start="handleStart"
@resume="handleResume"
@chapters="openChapterSelect"
@achievements="showAchievements = true"
@gallery="showEndingGallery = true"
@settings="store.setShowSettings(true)"
/>
<SaveLoadMenu
v-if="showMenu"
:saves="store.saves"
@@ -372,75 +371,6 @@ html, body {
color: #fff;
}
.game-end-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.8);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 100;
}
.game-end-text {
font-size: 36px;
letter-spacing: 4px;
}
.start-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.85);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 100;
}
.start-btn {
padding: 18px 48px;
font-size: 20px;
color: #fff;
background: rgba(255, 255, 255, 0.12);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
cursor: pointer;
letter-spacing: 4px;
transition: background 0.2s;
margin-top: 16px;
}
.start-btn:hover {
background: rgba(255, 255, 255, 0.25);
}
.resume-btn {
border-color: rgba(100, 200, 255, 0.3);
color: #8cf;
}
.chapters-btn {
border-color: rgba(255, 200, 100, 0.3);
color: #fc8;
}
.achievement-btn {
border-color: rgba(255, 193, 7, 0.3);
color: #ffc107;
}
.gallery-btn {
border-color: rgba(156, 39, 176, 0.3);
color: #ce93d8;
}
.settings-btn {
border-color: rgba(255, 255, 255, 0.3);
color: #aaa;
}
.pause-overlay {
position: fixed;
inset: 0;
@@ -465,29 +395,6 @@ html, body {
color: #888;
}
.game-end-actions {
margin-top: 24px;
display: flex;
gap: 12px;
justify-content: center;
}
.end-btn {
padding: 14px 32px;
font-size: 18px;
color: #fc8;
background: rgba(255, 200, 100, 0.08);
border: 1px solid rgba(255, 200, 100, 0.2);
border-radius: 4px;
cursor: pointer;
letter-spacing: 2px;
transition: background 0.2s;
}
.end-btn:hover {
background: rgba(255, 200, 100, 0.15);
}
.prompt-toast {
position: absolute;
top: 50%;

135
src/components/MainMenu.vue Normal file
View File

@@ -0,0 +1,135 @@
<script setup lang="ts">
import { useI18n } from '@/composables/useI18n'
import LangSwitch from '@/components/LangSwitch.vue'
defineProps<{
showResume: boolean
showChapters: boolean
showAchievements: boolean
showGallery: boolean
isGameEnd: boolean
}>()
const emit = defineEmits<{
start: []
resume: []
chapters: []
achievements: []
gallery: []
settings: []
}>()
const { t } = useI18n()
</script>
<template>
<div class="main-menu-overlay">
<div class="main-menu">
<div class="menu-top-bar">
<LangSwitch />
</div>
<h1 v-if="isGameEnd" class="menu-title">{{ t('ui.gameEnd') }}</h1>
<div class="menu-row primary-row">
<button class="menu-btn primary" @click="emit('start')">{{ t('ui.start') }}</button>
<button v-if="showResume" class="menu-btn secondary" @click="emit('resume')">{{ t('ui.resume') }}</button>
</div>
<div class="menu-row secondary-row">
<button v-if="showChapters" class="menu-btn tertiary" @click="emit('chapters')">{{ t('ui.chapters') }}</button>
<button v-if="showAchievements" class="menu-btn tertiary" @click="emit('achievements')">成就</button>
<button v-if="showGallery" class="menu-btn tertiary" @click="emit('gallery')">画廊</button>
<button class="menu-btn tertiary" @click="emit('settings')">设置</button>
</div>
</div>
</div>
</template>
<style scoped>
.main-menu-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.88);
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
}
.main-menu {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.menu-top-bar {
margin-bottom: 8px;
}
.menu-title {
font-size: 36px;
font-weight: 400;
letter-spacing: 6px;
color: #ddd;
margin-bottom: 8px;
}
.menu-row {
display: flex;
gap: 12px;
}
.menu-btn {
padding: 16px 40px;
font-size: 18px;
color: #fff;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
cursor: pointer;
letter-spacing: 2px;
transition: background 0.2s;
}
.menu-btn:hover {
background: rgba(255, 255, 255, 0.12);
}
.menu-btn.primary {
background: rgba(255, 255, 255, 0.1);
padding: 18px 56px;
font-size: 22px;
letter-spacing: 4px;
}
.menu-btn.primary:hover {
background: rgba(255, 255, 255, 0.2);
}
.menu-btn.secondary {
background: rgba(100, 200, 255, 0.08);
border-color: rgba(100, 200, 255, 0.3);
color: #8cf;
font-size: 16px;
padding: 16px 36px;
}
.menu-btn.secondary:hover {
background: rgba(100, 200, 255, 0.15);
}
.menu-btn.tertiary {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.15);
color: #aaa;
font-size: 14px;
padding: 12px 28px;
letter-spacing: 1px;
}
.menu-btn.tertiary:hover {
background: rgba(255, 255, 255, 0.1);
color: #ddd;
}
</style>