Explorar o código

turtlesoupsettings使用新的数据结构

wuzj hai 2 días
pai
achega
7a83b8317c
Modificáronse 1 ficheiros con 98 adicións e 79 borrados
  1. 98 79
      src/components/room/host/gamesettings/TurtleSoupSettings.vue

+ 98 - 79
src/components/room/host/gamesettings/TurtleSoupSettings.vue

@@ -6,15 +6,15 @@
       <div class="settings-info">
         <div class="settings-row">
           <div class="settings-label">主题:</div>
-          <div class="settings-value">{{ selectedTheme.themeName }}</div>
+          <div class="settings-value">{{ themeName }}</div>
         </div>
         <div class="settings-row">
           <div class="settings-label">难度:</div>
-          <div class="settings-badge">{{ selectedTheme.difficultyName }}</div>
+          <div class="settings-badge">{{ difficultyName }}</div>
         </div>
         <div class="settings-row">
           <div class="settings-label">题目:</div>
-          <div class="settings-value">{{ selectedTheme.puzzleName }}</div>
+          <div class="settings-value">{{ puzzleName }}</div>
         </div>
       </div>
       
@@ -45,9 +45,9 @@
           
           <div class="theme-list">
             <div v-for="theme in themes" 
-                :key="theme.id" 
+                :key="theme.themeId" 
                 class="theme-item"
-                :class="{ 'selected': selectedTheme.theme === theme.id, 'locked': theme.isLocked }"
+                :class="{ 'selected': selectedSettings.themeId === theme.themeId, 'locked': theme.isLocked }"
                 @click="!theme.isLocked && selectTheme(theme)">
               <div class="theme-icon">
                 <IconFont :name="getIconName(theme)" size="20" color="#FF9F2D" />
@@ -83,8 +83,8 @@
             <nut-button 
               v-for="diff in difficulties" 
               :key="diff.id"
-              :type="selectedTheme.difficulty === diff.id ? 'primary' : 'default'"
-              :color="selectedTheme.difficulty === diff.id ? '#FF9F2D' : ''"
+              :type="selectedSettings.difficulty === diff.id ? 'primary' : 'default'"
+              :color="selectedSettings.difficulty === diff.id ? '#FF9F2D' : ''"
               class="difficulty-btn"
               @click="selectDifficulty(diff)">
               {{ diff.name }}
@@ -131,16 +131,16 @@
           <!-- 题目列表 -->
           <div v-else class="puzzle-list">
             <div v-for="puzzle in filteredPuzzles" 
-                :key="puzzle.id" 
+                :key="puzzle.puzzleId" 
                 class="puzzle-item"
-                :class="{ 'selected': selectedTheme.puzzle === puzzle.id }"
+                :class="{ 'selected': selectedSettings.puzzleId === puzzle.puzzleId }"
                 @click="selectPuzzle(puzzle)">
               <div class="puzzle-header">
-                <div class="puzzle-name">{{ puzzle.name }}</div>
-                <div class="puzzle-meta">{{ selectedTheme.difficultyName }} · {{ puzzle.duration }}</div>
+                <div class="puzzle-name">{{ puzzle.title }}</div>
+                <div class="puzzle-meta">{{ difficultyName }} · {{ puzzle.duration }}</div>
               </div>
               <div class="puzzle-desc">{{ puzzle.desc }}</div>
-              <IconFont v-if="selectedTheme.puzzle === puzzle.id" 
+              <IconFont v-if="selectedSettings.puzzleId === puzzle.puzzleId" 
                        name="check" 
                        size="16" 
                        color="#FF9F2D" 
@@ -158,11 +158,12 @@
   </div>
 </template>
 
-<script setup>
-import { ref, computed, reactive, onMounted } from 'vue';
+<script setup lang="ts">
+import { ref, computed, reactive, onMounted, watch } from 'vue';
 import { useTurtleSoupStore } from '@/stores/games/turtlesoup';
 import Taro from '@tarojs/taro';
 import { IconFont } from '@nutui/icons-vue-taro';
+import { TurtleSoupGameSettings, TurtleSoupDifficulty, TurtleSoupTheme, TurtleSoupPuzzle } from '@/types/games/turtlesoup';
 
 // 获取海龟汤store
 const turtleSoupStore = useTurtleSoupStore();
@@ -181,54 +182,64 @@ const loading = ref({
   puzzles: false
 });
 
-// 主题数据
-const themes = ref([]);
+// 1. 只保存 settings
+const selectedSettings = reactive<TurtleSoupGameSettings>({
+  themeId: '',
+  puzzleId: '',
+  difficulty: TurtleSoupDifficulty.EASY,
+  maxPlayers: 10,
+  password: ''
+});
+
+// 2. 主题、题目数据
+const themes = ref<TurtleSoupTheme[]>([]);
+const puzzles = ref<TurtleSoupPuzzle[]>([]);
+
+// 3. 展示用 computed
+const themeObj = computed(() => themes.value.find(t => t.themeId === selectedSettings.themeId));
+const puzzleObj = computed(() => puzzles.value.find(p => p.puzzleId === selectedSettings.puzzleId));
+const themeName = computed(() => themeObj.value?.name || '');
+const puzzleName = computed(() => puzzleObj.value?.title || '');
+const difficultyName = computed(() => {
+  switch (selectedSettings.difficulty) {
+    case TurtleSoupDifficulty.EASY: return '简单';
+    case TurtleSoupDifficulty.MEDIUM: return '中等';
+    case TurtleSoupDifficulty.HARD: return '困难';
+    default: return '';
+  }
+});
+
+// 4. 主题/题目筛选
+const filteredPuzzles = computed(() =>
+  puzzles.value.filter(p =>
+    p.themeId === selectedSettings.themeId &&
+    p.difficulty === selectedSettings.difficulty
+  )
+);
 
 // 难度数据
 const difficulties = [
-  { id: 'easy', name: '简单' },
-  { id: 'medium', name: '中等' },
-  { id: 'hard', name: '困难' },
+  { id: TurtleSoupDifficulty.EASY, name: '简单' },
+  { id: TurtleSoupDifficulty.MEDIUM, name: '中等' },
+  { id: TurtleSoupDifficulty.HARD, name: '困难' },
 ];
 
 // 难度描述
 const difficultyDescription = computed(() => {
-  switch(selectedTheme.difficulty) {
-    case 'easy':
+  switch(selectedSettings.difficulty) {
+    case TurtleSoupDifficulty.EASY:
       return '简单难度适合初次接触海龟汤的玩家,解题时间约10-15分钟。';
-    case 'medium':
+    case TurtleSoupDifficulty.MEDIUM:
       return '中等难度需要一定的逻辑思维能力,解题时间约15-25分钟。';
-    case 'hard':
+    case TurtleSoupDifficulty.HARD:
       return '困难难度挑战你的思维极限,解题时间约25-40分钟。';
     default:
       return '选择一个难度查看详情';
   }
 });
 
-// 谜题数据
-const puzzles = ref([]);
-
-// 根据主题和难度筛选谜题
-const filteredPuzzles = computed(() => {
-  return puzzles.value.filter(puzzle => 
-    puzzle.theme === selectedTheme.theme && 
-    puzzle.difficulty === selectedTheme.difficulty
-  );
-});
-
-// 当前选择的数据
-const selectedTheme = reactive({
-  theme: '',
-  themeName: '',
-  themePrice: '',
-  difficulty: 'easy',
-  difficultyName: '简单',
-  puzzle: '',
-  puzzleName: ''
-});
-
 // 获取IconFont组件支持的图标名称
-const getIconName = (theme) => {
+const getIconName = (theme: TurtleSoupTheme) => {
   const iconMap = {
     'classic': 'bookmark',
     'universal': 'location',
@@ -250,7 +261,7 @@ const loadThemes = async () => {
     
     if (themeData && themeData.length) {
       themes.value = themeData.map(theme => ({
-        id: theme.id,
+        themeId: theme.themeId,
         name: theme.name,
         price: theme.price ? `${theme.price}元/小时` : '免费',
         desc: theme.description || '主题介绍',
@@ -262,7 +273,7 @@ const loadThemes = async () => {
       console.log('主题列表加载成功,数量:', themes.value.length);
       
       // 如果没有选择主题,默认选择第一个未锁定的主题
-      if (!selectedTheme.theme) {
+      if (!selectedSettings.themeId) {
         const defaultTheme = themes.value.find(theme => !theme.isLocked);
         if (defaultTheme) {
           console.log('自动选择默认主题:', defaultTheme.name);
@@ -285,36 +296,36 @@ const loadThemes = async () => {
 
 // 加载题目列表
 const loadPuzzles = async () => {
-  if (!selectedTheme.theme) {
+  if (!selectedSettings.themeId) {
     console.warn('加载题目前需要先选择主题');
     return;
   }
   
   try {
     loading.value.puzzles = true;
-    console.log('开始加载题目,主题:', selectedTheme.theme, '难度:', selectedTheme.difficulty);
+    console.log('开始加载题目,主题:', selectedSettings.themeId, '难度:', selectedSettings.difficulty);
     
     // 从turtleSoupStore加载题目
     const puzzleData = await turtleSoupStore.loadPuzzles(
-      selectedTheme.theme, 
-      selectedTheme.difficulty
+      selectedSettings.themeId, 
+      selectedSettings.difficulty
     );
     
     if (puzzleData && puzzleData.length) {
       puzzles.value = puzzleData.map(puzzle => ({
-        id: puzzle.id,
-        name: puzzle.title || '未命名题目',
+        puzzleId: puzzle.puzzleId,
+        title: puzzle.title || '未命名题目',
         difficulty: puzzle.difficulty,
         duration: puzzle.averageDuration || '平均用时20分钟',
         desc: puzzle.description || '题目描述',
-        theme: puzzle.themeId
+        themeId: puzzle.themeId
       }));
       
       console.log('题目加载成功,数量:', puzzles.value.length);
       
       // 如果没有选择题目,默认选择第一个题目
-      if (!selectedTheme.puzzle && filteredPuzzles.value.length > 0) {
-        console.log('自动选择默认题目:', filteredPuzzles.value[0].name);
+      if (!selectedSettings.puzzleId && filteredPuzzles.value.length > 0) {
+        console.log('自动选择默认题目:', filteredPuzzles.value[0].title);
         selectPuzzle(filteredPuzzles.value[0]);
       }
     } else {
@@ -365,10 +376,10 @@ const prevStep = () => {
 };
 
 // 选择主题
-const selectTheme = (theme) => {
-  selectedTheme.theme = theme.id;
-  selectedTheme.themeName = theme.name;
-  selectedTheme.themePrice = theme.price;
+const selectTheme = (theme: TurtleSoupTheme) => {
+  selectedSettings.themeId = theme.themeId;
+  // 主题变更时重置题目
+  selectedSettings.puzzleId = '';
   console.log('选择主题:', theme.name);
   
   // 更新到store或emit事件
@@ -376,20 +387,20 @@ const selectTheme = (theme) => {
 };
 
 // 选择难度
-const selectDifficulty = (difficulty) => {
-  selectedTheme.difficulty = difficulty.id;
-  selectedTheme.difficultyName = difficulty.name;
-  console.log('选择难度:', difficulty.name);
+const selectDifficulty = (difficulty: TurtleSoupDifficulty) => {
+  selectedSettings.difficulty = difficulty;
+  // 难度变更时重置题目
+  selectedSettings.puzzleId = '';
+  console.log('选择难度:', difficulty);
   
   // 更新到store或emit事件
   updateSelection();
 };
 
 // 选择谜题
-const selectPuzzle = (puzzle) => {
-  selectedTheme.puzzle = puzzle.id;
-  selectedTheme.puzzleName = puzzle.name;
-  console.log('选择题目:', puzzle.name);
+const selectPuzzle = (puzzle: TurtleSoupPuzzle) => {
+  selectedSettings.puzzleId = puzzle.puzzleId;
+  console.log('选择题目:', puzzle.title);
   
   // 更新到store或emit事件
   updateSelection();
@@ -398,11 +409,11 @@ const selectPuzzle = (puzzle) => {
 // 确认选择
 const confirmSelection = () => {
   // 确保选择了题目
-  if (!selectedTheme.puzzle && filteredPuzzles.value.length > 0) {
+  if (!selectedSettings.puzzleId && filteredPuzzles.value.length > 0) {
     selectPuzzle(filteredPuzzles.value[0]);
   }
   
-  console.log('确认选择:', selectedTheme);
+  console.log('确认选择:', selectedSettings);
   
   // 更新到store或emit事件
   updateSelection();
@@ -417,7 +428,7 @@ const selectRandomPuzzle = () => {
     const randomIndex = Math.floor(Math.random() * filteredPuzzles.value.length);
     const randomPuzzle = filteredPuzzles.value[randomIndex];
     selectPuzzle(randomPuzzle);
-    console.log('随机选择题目:', randomPuzzle.name);
+    console.log('随机选择题目:', randomPuzzle.title);
     
     // 显示提示
     Taro.showToast({
@@ -437,17 +448,17 @@ const selectRandomPuzzle = () => {
 
 // 更新选择,发出事件
 const updateSelection = () => {
-  emit('selection-change', { ...selectedTheme });
+  emit('selection-change', { ...selectedSettings });
 };
 
 // 购买主题 - 使用微信支付
-const purchaseTheme = async (theme) => {
+const purchaseTheme = async (theme: TurtleSoupTheme) => {
   try {
     Taro.showLoading({ title: '准备支付...' });
     console.log('准备购买主题:', theme.name);
     
     // 调用store方法获取支付参数
-    const paymentParams = await turtleSoupStore.getThemePaymentParams(theme.id);
+    const paymentParams = await turtleSoupStore.getThemePaymentParams(theme.themeId);
     
     if (!paymentParams) {
       throw new Error('获取支付参数失败');
@@ -470,7 +481,7 @@ const purchaseTheme = async (theme) => {
         
         try {
           // 调用解锁主题API
-          const result = await turtleSoupStore.unlockTheme(theme.id);
+          const result = await turtleSoupStore.unlockTheme(theme.themeId);
           
           if (result && result.success) {
             console.log('主题解锁成功');
@@ -483,7 +494,7 @@ const purchaseTheme = async (theme) => {
             await loadThemes();
             
             // 选择刚解锁的主题
-            const updatedTheme = themes.value.find(t => t.id === theme.id);
+            const updatedTheme = themes.value.find(t => t.themeId === theme.themeId);
             if (updatedTheme && !updatedTheme.isLocked) {
               selectTheme(updatedTheme);
             }
@@ -536,14 +547,22 @@ onMounted(async () => {
   // 如果传入了初始主题,使用传入的初始值
   if (Object.keys(props.initialTheme).length > 0) {
     console.log('使用传入的初始主题:', props.initialTheme);
-    Object.assign(selectedTheme, props.initialTheme);
+    Object.assign(selectedSettings, props.initialTheme);
     
     // 初始化后加载题目
-    if (selectedTheme.theme) {
+    if (selectedSettings.themeId) {
       await loadPuzzles();
     }
   }
 });
+
+// 监听 themeId/difficulty 变化自动加载题目
+watch(() => [selectedSettings.themeId, selectedSettings.difficulty], async ([themeId, diff], [oldThemeId, oldDiff]) => {
+  if (themeId && (themeId !== oldThemeId || diff !== oldDiff)) {
+    await loadPuzzles();
+    selectedSettings.puzzleId = '';
+  }
+});
 </script>
 
 <style lang="scss">