feat: main menu component, roadmap update
This commit is contained in:
123
src/App.vue
123
src/App.vue
@@ -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
135
src/components/MainMenu.vue
Normal 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>
|
||||
Reference in New Issue
Block a user