|
@@ -1,70 +1,431 @@
|
|
|
-//海龟汤游戏特定的状态管理
|
|
|
+// stores/games/turtlesoup.ts
|
|
|
import { defineStore } from 'pinia'
|
|
|
-import { turtleSoupService } from '@/services/api/games'
|
|
|
-
|
|
|
-// 海龟汤游戏状态
|
|
|
-export interface TurtleSoupGame {
|
|
|
- id: string
|
|
|
- title: string
|
|
|
- story: string
|
|
|
- solution: string
|
|
|
- hints: string[]
|
|
|
- questions: TurtleSoupQuestion[]
|
|
|
- // ... 其他特定字段
|
|
|
-}
|
|
|
-
|
|
|
-export interface TurtleSoupQuestion {
|
|
|
- id: string
|
|
|
- content: string
|
|
|
- answer: string
|
|
|
- askedBy: string
|
|
|
- timestamp: number
|
|
|
-}
|
|
|
+import { turtleSoupService } from '@/services/games/turtlesoup'
|
|
|
+import {
|
|
|
+ type TurtleSoupGame,
|
|
|
+ type TurtleSoupQuestion,
|
|
|
+ type TurtleSoupHint,
|
|
|
+ type TurtleSoupGameResult,
|
|
|
+ type TurtleSoupAnswerType
|
|
|
+} from '@/types/games/turtlesoup'
|
|
|
+import { useUserStore } from '@/stores/user'
|
|
|
|
|
|
export const useTurtleSoupStore = defineStore('turtlesoup', {
|
|
|
state: () => ({
|
|
|
currentGame: null as TurtleSoupGame | null,
|
|
|
loading: false,
|
|
|
- revealedHints: [] as number[],
|
|
|
- // ... 其他状态
|
|
|
+ submitting: false,
|
|
|
+ error: null as string | null,
|
|
|
+ userRole: 'player' as 'player' | 'storyteller',
|
|
|
+ pendingQuestions: [] as TurtleSoupQuestion[], // 待回答的问题
|
|
|
+ isSolved: false,
|
|
|
+ // 用于本地临时存储
|
|
|
+ localDraft: '', // 问题/解答草稿
|
|
|
}),
|
|
|
|
|
|
+ getters: {
|
|
|
+ // 获取已公开的提示
|
|
|
+ revealedHints(): TurtleSoupHint[] {
|
|
|
+ if (!this.currentGame) return [];
|
|
|
+ return this.currentGame.hints.filter(hint => hint.revealed);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取未公开的提示
|
|
|
+ unrevealedHints(): TurtleSoupHint[] {
|
|
|
+ if (!this.currentGame) return [];
|
|
|
+ return this.currentGame.hints.filter(hint => !hint.revealed);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取排序后的问题列表(最新的在前)
|
|
|
+ sortedQuestions(): TurtleSoupQuestion[] {
|
|
|
+ if (!this.currentGame) return [];
|
|
|
+ return [...this.currentGame.questions].sort((a, b) =>
|
|
|
+ new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
+ // 游戏是否激活
|
|
|
+ isGameActive(): boolean {
|
|
|
+ return this.currentGame?.status === 'active';
|
|
|
+ },
|
|
|
+
|
|
|
+ // 当前用户是否为主持人
|
|
|
+ isStoryteller(): boolean {
|
|
|
+ if (!this.currentGame) return false;
|
|
|
+ const userStore = useUserStore();
|
|
|
+ return this.currentGame.storyteller === userStore.openid;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取游戏时长(秒)
|
|
|
+ gameDuration(): number {
|
|
|
+ if (!this.currentGame || !this.currentGame.startTime) return 0;
|
|
|
+
|
|
|
+ const start = new Date(this.currentGame.startTime).getTime();
|
|
|
+ const end = this.currentGame.endTime
|
|
|
+ ? new Date(this.currentGame.endTime).getTime()
|
|
|
+ : Date.now();
|
|
|
+
|
|
|
+ return Math.floor((end - start) / 1000);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
actions: {
|
|
|
+ // 重置状态
|
|
|
+ resetState() {
|
|
|
+ this.currentGame = null;
|
|
|
+ this.loading = false;
|
|
|
+ this.submitting = false;
|
|
|
+ this.error = null;
|
|
|
+ this.userRole = 'player';
|
|
|
+ this.pendingQuestions = [];
|
|
|
+ this.isSolved = false;
|
|
|
+ this.localDraft = '';
|
|
|
+ },
|
|
|
+
|
|
|
// 加载游戏数据
|
|
|
- async loadGame(gameId: string, role: string) {
|
|
|
- this.loading = true
|
|
|
+ async loadGame(gameId: string, role = 'player') {
|
|
|
+ this.loading = true;
|
|
|
+ this.error = null;
|
|
|
+ this.userRole = role as 'player' | 'storyteller';
|
|
|
+
|
|
|
try {
|
|
|
- const result = await turtleSoupService.getGameData(gameId, role)
|
|
|
- if (result && result.game) {
|
|
|
- this.currentGame = result.game
|
|
|
- return true
|
|
|
+ const result = await turtleSoupService.getGameData(gameId, role);
|
|
|
+
|
|
|
+ if (result.success && result.data) {
|
|
|
+ this.currentGame = result.data;
|
|
|
+
|
|
|
+ // 如果是讲述者,找出待回答的问题
|
|
|
+ if (role === 'storyteller') {
|
|
|
+ this.pendingQuestions = result.data.questions.filter(q => !q.answered);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ this.error = result.message || '加载游戏数据失败';
|
|
|
+ return false;
|
|
|
}
|
|
|
- return false
|
|
|
} catch (error) {
|
|
|
- console.error('加载海龟汤游戏失败:', error)
|
|
|
- return false
|
|
|
+ console.error('加载海龟汤游戏失败:', error);
|
|
|
+ this.error = error instanceof Error ? error.message : '未知错误';
|
|
|
+ return false;
|
|
|
} finally {
|
|
|
- this.loading = false
|
|
|
+ this.loading = false;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
// 提交问题
|
|
|
async submitQuestion(content: string) {
|
|
|
- if (!this.currentGame) return false
|
|
|
+ if (!this.currentGame || !content.trim()) {
|
|
|
+ this.error = '无效的问题或游戏未加载';
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.submitting = true;
|
|
|
+ this.error = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const result = await turtleSoupService.submitQuestion(this.currentGame.id, content);
|
|
|
+
|
|
|
+ if (result.success && result.data?.questionId) {
|
|
|
+ // 获取用户信息
|
|
|
+ const userStore = useUserStore();
|
|
|
+
|
|
|
+ // 创建新问题对象
|
|
|
+ const newQuestion: TurtleSoupQuestion = {
|
|
|
+ id: result.data.questionId,
|
|
|
+ content,
|
|
|
+ askedBy: userStore.openid,
|
|
|
+ askedByName: userStore.userInfo?.nickname,
|
|
|
+ timestamp: new Date().toISOString(),
|
|
|
+ answered: false
|
|
|
+ };
|
|
|
+
|
|
|
+ // 更新本地游戏状态
|
|
|
+ if (this.currentGame) {
|
|
|
+ this.currentGame = {
|
|
|
+ ...this.currentGame,
|
|
|
+ questions: [...this.currentGame.questions, newQuestion]
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清空草稿
|
|
|
+ this.localDraft = '';
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ this.error = result.message || '提交问题失败';
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('提交问题失败:', error);
|
|
|
+ this.error = error instanceof Error ? error.message : '提交问题时发生错误';
|
|
|
+ return false;
|
|
|
+ } finally {
|
|
|
+ this.submitting = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 回答问题(讲述者)
|
|
|
+ async answerQuestion(questionId: string, answer: TurtleSoupAnswerType) {
|
|
|
+ if (!this.currentGame || this.userRole !== 'storyteller') {
|
|
|
+ this.error = '无权限回答问题';
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.submitting = true;
|
|
|
+ this.error = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const result = await turtleSoupService.answerQuestion(questionId, answer);
|
|
|
+
|
|
|
+ if (result.success && result.data?.success) {
|
|
|
+ // 更新本地状态
|
|
|
+ if (this.currentGame) {
|
|
|
+ const updatedQuestions = this.currentGame.questions.map(q => {
|
|
|
+ if (q.id === questionId) {
|
|
|
+ return {
|
|
|
+ ...q,
|
|
|
+ answer,
|
|
|
+ answered: true,
|
|
|
+ answeredAt: new Date().toISOString()
|
|
|
+ };
|
|
|
+ }
|
|
|
+ return q;
|
|
|
+ });
|
|
|
+
|
|
|
+ this.currentGame = {
|
|
|
+ ...this.currentGame,
|
|
|
+ questions: updatedQuestions
|
|
|
+ };
|
|
|
+
|
|
|
+ // 从待回答列表中移除
|
|
|
+ this.pendingQuestions = this.pendingQuestions.filter(q => q.id !== questionId);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ this.error = result.message || '回答问题失败';
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('回答问题失败:', error);
|
|
|
+ this.error = error instanceof Error ? error.message : '回答问题时发生错误';
|
|
|
+ return false;
|
|
|
+ } finally {
|
|
|
+ this.submitting = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 公开提示
|
|
|
+ async revealHint(hintIndex: number) {
|
|
|
+ if (!this.currentGame || this.userRole !== 'storyteller') {
|
|
|
+ this.error = '无权限公开提示';
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查索引是否有效
|
|
|
+ if (hintIndex < 0 || hintIndex >= (this.currentGame.hints?.length || 0)) {
|
|
|
+ this.error = '无效的提示索引';
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.submitting = true;
|
|
|
+ this.error = null;
|
|
|
|
|
|
try {
|
|
|
- const result = await turtleSoupService.submitQuestion(this.currentGame.id, content)
|
|
|
- if (result && result.questionId) {
|
|
|
- // 更新本地状态...
|
|
|
- return true
|
|
|
+ const result = await turtleSoupService.revealHint(this.currentGame.id, hintIndex);
|
|
|
+
|
|
|
+ if (result.success && result.data?.success) {
|
|
|
+ // 更新本地状态
|
|
|
+ if (this.currentGame) {
|
|
|
+ const updatedHints = this.currentGame.hints.map((hint, index) => {
|
|
|
+ if (index === hintIndex) {
|
|
|
+ return {
|
|
|
+ ...hint,
|
|
|
+ revealed: true,
|
|
|
+ revealedAt: new Date().toISOString()
|
|
|
+ };
|
|
|
+ }
|
|
|
+ return hint;
|
|
|
+ });
|
|
|
+
|
|
|
+ this.currentGame = {
|
|
|
+ ...this.currentGame,
|
|
|
+ hints: updatedHints
|
|
|
+ };
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ this.error = result.message || '公开提示失败';
|
|
|
+ return false;
|
|
|
}
|
|
|
- return false
|
|
|
} catch (error) {
|
|
|
- console.error('提交问题失败:', error)
|
|
|
- return false
|
|
|
+ console.error('公开提示失败:', error);
|
|
|
+ this.error = error instanceof Error ? error.message : '公开提示时发生错误';
|
|
|
+ return false;
|
|
|
+ } finally {
|
|
|
+ this.submitting = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 提交解答
|
|
|
+ async submitSolution(solution: string) {
|
|
|
+ if (!this.currentGame || !solution.trim()) {
|
|
|
+ this.error = '无效的解答或游戏未加载';
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.submitting = true;
|
|
|
+ this.error = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const result = await turtleSoupService.submitSolution(this.currentGame.id, solution);
|
|
|
+
|
|
|
+ if (result.success) {
|
|
|
+ // 如果答案正确
|
|
|
+ if (result.data?.correct) {
|
|
|
+ this.isSolved = true;
|
|
|
+ // 获取用户信息
|
|
|
+ const userStore = useUserStore();
|
|
|
+
|
|
|
+ // 结束游戏
|
|
|
+ await this.endGame({
|
|
|
+ solved: true,
|
|
|
+ solvedBy: userStore.openid
|
|
|
+ });
|
|
|
+
|
|
|
+ return { success: true, correct: true };
|
|
|
+ }
|
|
|
+
|
|
|
+ // 答案错误
|
|
|
+ return { success: true, correct: false };
|
|
|
+ } else {
|
|
|
+ this.error = result.message || '提交解答失败';
|
|
|
+ return { success: false, correct: false };
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('提交解答失败:', error);
|
|
|
+ this.error = error instanceof Error ? error.message : '提交解答时发生错误';
|
|
|
+ return { success: false, correct: false };
|
|
|
+ } finally {
|
|
|
+ this.submitting = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 结束游戏
|
|
|
+ async endGame(result: { solved: boolean; solvedBy?: string }) {
|
|
|
+ if (!this.currentGame) {
|
|
|
+ this.error = '游戏未加载';
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.submitting = true;
|
|
|
+ this.error = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await turtleSoupService.endGame(this.currentGame.id, result);
|
|
|
+
|
|
|
+ if (response.success && response.data) {
|
|
|
+ // 更新游戏状态
|
|
|
+ if (this.currentGame) {
|
|
|
+ this.currentGame = {
|
|
|
+ ...this.currentGame,
|
|
|
+ status: 'completed',
|
|
|
+ endTime: new Date().toISOString()
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ return response.data;
|
|
|
+ } else {
|
|
|
+ this.error = response.message || '结束游戏失败';
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('结束游戏失败:', error);
|
|
|
+ this.error = error instanceof Error ? error.message : '结束游戏时发生错误';
|
|
|
+ return null;
|
|
|
+ } finally {
|
|
|
+ this.submitting = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 创建新游戏
|
|
|
+ async createGame(gameData: {
|
|
|
+ title: string;
|
|
|
+ description: string;
|
|
|
+ solution: string;
|
|
|
+ hints: string[];
|
|
|
+ difficulty: string;
|
|
|
+ }) {
|
|
|
+ this.submitting = true;
|
|
|
+ this.error = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const result = await turtleSoupService.createGame(gameData);
|
|
|
+
|
|
|
+ if (result.success && result.data?.gameId) {
|
|
|
+ // 成功创建游戏
|
|
|
+ return result.data.gameId;
|
|
|
+ } else {
|
|
|
+ this.error = result.message || '创建游戏失败';
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('创建游戏失败:', error);
|
|
|
+ this.error = error instanceof Error ? error.message : '创建游戏时发生错误';
|
|
|
+ return null;
|
|
|
+ } finally {
|
|
|
+ this.submitting = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取用户创建的游戏列表
|
|
|
+ async fetchCreatedGames() {
|
|
|
+ this.loading = true;
|
|
|
+ this.error = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const result = await turtleSoupService.getCreatedGames();
|
|
|
+
|
|
|
+ if (result.success) {
|
|
|
+ return result.data || [];
|
|
|
+ } else {
|
|
|
+ this.error = result.message || '获取创建的游戏列表失败';
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取创建的游戏列表失败:', error);
|
|
|
+ this.error = error instanceof Error ? error.message : '获取游戏列表时发生错误';
|
|
|
+ return [];
|
|
|
+ } finally {
|
|
|
+ this.loading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取用户参与的游戏列表
|
|
|
+ async fetchJoinedGames() {
|
|
|
+ this.loading = true;
|
|
|
+ this.error = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const result = await turtleSoupService.getJoinedGames();
|
|
|
+
|
|
|
+ if (result.success) {
|
|
|
+ return result.data || [];
|
|
|
+ } else {
|
|
|
+ this.error = result.message || '获取参与的游戏列表失败';
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取参与的游戏列表失败:', error);
|
|
|
+ this.error = error instanceof Error ? error.message : '获取游戏列表时发生错误';
|
|
|
+ return [];
|
|
|
+ } finally {
|
|
|
+ this.loading = false;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
- // ... 其他方法
|
|
|
+ // 保存问题草稿
|
|
|
+ saveDraft(content: string) {
|
|
|
+ this.localDraft = content;
|
|
|
+ }
|
|
|
}
|
|
|
-})
|
|
|
+});
|