feat: P15 ending gallery, chapter recap, visited tracking, save system v6

This commit is contained in:
2026-06-09 17:49:07 +08:00
parent 47d6ce50fe
commit 9297117544
14 changed files with 517 additions and 48 deletions

View File

@@ -11,6 +11,8 @@ import PlaybackBar from '@/components/PlaybackBar.vue'
import LangSwitch from '@/components/LangSwitch.vue'
import AchievementToast from '@/components/AchievementToast.vue'
import AchievementPanel from '@/components/AchievementPanel.vue'
import EndingGallery from '@/components/EndingGallery.vue'
import ChapterRecap from '@/components/ChapterRecap.vue'
import { useGameEngine } from '@/composables/useGameEngine'
import { useGameStore } from '@/stores/gameStore'
import { useFullscreen } from '@/composables/useFullscreen'
@@ -26,6 +28,8 @@ const started = ref(false)
const showMenu = ref(false)
const showChapterSelect = ref(false)
const showAchievements = ref(false)
const showEndingGallery = ref(false)
const recapChapterId = ref<string | null>(null)
const hasAutoSave = ref(false)
const currentSpeed = ref(1)
const canSkip = ref(false)
@@ -34,7 +38,7 @@ const showPromptToast = ref(false)
const { loadGame, start, resumeAutoSave, makeChoice, clickHotspot, startChapter,
skipScene, setSpeed, getSpeed, isSceneWatched,
saveGame, loadGameFromSlot, refreshSaves, saveSystem } =
saveGame, loadGameFromSlot, refreshSaves, saveSystem, engine } =
useGameEngine(() => [videoElA.value, videoElB.value])
async function init() {
@@ -203,6 +207,7 @@ init()
<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>
</div>
<div v-if="store.gameEnded" class="game-end-overlay">
<div class="game-end-text">{{ t('ui.gameEnd') }}</div>
@@ -230,6 +235,19 @@ init()
:unlocked-ids="store.unlockedAchievementIds"
@close="showAchievements = false"
/>
<EndingGallery
v-if="showEndingGallery"
:endings="store.endings"
:visited-ids="store.visitedSceneIds"
@close="showEndingGallery = false"
/>
<ChapterRecap
v-if="recapChapterId"
:chapter="store.chapters.find(c => c.id === recapChapterId)!"
:scenes="engine.sceneManager.getScenes()"
:visited-ids="store.visitedSceneIds"
@close="recapChapterId = null"
/>
<AchievementToast
:achievement-id="store.toastAchievementId"
:definitions="store.achievementDefs"
@@ -366,6 +384,11 @@ html, body {
color: #ffc107;
}
.gallery-btn {
border-color: rgba(156, 39, 176, 0.3);
color: #ce93d8;
}
.game-end-actions {
margin-top: 24px;
display: flex;