import type { CompetitionData } from '@/views/user/types' import { defineStore } from 'pinia' import { computed, ref } from 'vue' import { useRouterPush } from '@/hooks/common/router' import { AudioController } from '@/utils/audio' import { mockData } from '@/views/user/data/mock' export const useCompetitionStore = defineStore('competition', () => { const { routerPushByKey } = useRouterPush() // --- State --- const data = ref(mockData) const currentStep = ref(0) // Node 索引 const subStep = ref(0) // Question 索引 const timeLeft = ref(0) const timerInterval = ref(null) // 音效控制器 (支持自定义音频文件,例如:{ start: '/audio/start.mp3' }) const audioController = new AudioController() // --- Getters --- const currentNode = computed(() => data.value.nodes[currentStep.value]) const currentQuestion = computed(() => { const questions = currentNode.value?.questions || [] return questions[subStep.value] || questions[0] }) const isLastQuestionInNode = computed(() => { if (!currentNode.value) return true return subStep.value >= currentNode.value.questions.length - 1 }) const isLastNode = computed(() => { return currentStep.value >= data.value.nodes.length - 1 }) // --- Actions --- function initData() { // 这里可以重置或者重新拉取数据 // data.value = ... resetProgress() } function resetProgress() { currentStep.value = 0 subStep.value = 0 stopTimer() } // --- Audio Helpers --- // 音频相关逻辑已抽离到 @/utils/audio.ts /** * 启动倒计时定时器 */ function startTimer() { stopTimer() if (!currentNode.value) return timeLeft.value = currentNode.value.config.timeLimit audioController.play('start') // 播放开始音效 timerInterval.value = window.setInterval(() => { if (timeLeft.value > 0) { timeLeft.value-- // 剩余5秒播放倒计时音效 if (timeLeft.value <= 5) { audioController.play('tick') } } else { stopTimer() // 时间到,自动进入解析页 routerPushByKey('user_analysis') } }, 1000) } function stopTimer() { if (timerInterval.value) { clearInterval(timerInterval.value) timerInterval.value = null } } /** * 进入下一题或下一环节 * @returns 返回下一步的路由名称,方便组件跳转 */ function nextStep() { stopTimer() // A. 如果当前环节还有题 if (!isLastQuestionInNode.value) { subStep.value++ // 回到抽题页 return 'user_draw' } // B. 当前环节结束,去下一个环节 else if (!isLastNode.value) { currentStep.value++ subStep.value = 0 // 回到抽题页(新环节) return 'user_draw' } // C. 全部结束 else { resetProgress() return 'user_cover' } } return { data, currentStep, subStep, timeLeft, currentNode, currentQuestion, initData, startTimer, stopTimer, nextStep, } })