Эх сурвалжийг харах

保持房间最大最小人数前后一致性

wuzj 6 өдөр өмнө
parent
commit
8a90ed6727

+ 241 - 3
src/pages/game-detail/index.vue

@@ -11,7 +11,7 @@
             <view class="game-stats">
               <view class="game-players">
                 <people size="14"></people>
-                <text>{{ game.players }}人</text>
+                <text>{{ game.minPlayers }} - {{ game.maxPlayers }}人</text>
               </view>
               <view class="game-duration">
                 <clock size="14"></clock>
@@ -248,6 +248,244 @@ export default {
 }
 </script>
 
-<style>
-/* 样式保持不变 */
+<style lang="scss">
+.game-detail-page {
+  background-color: $background-color-base;
+  min-height: 100vh;
+  position: relative;
+
+  .game-detail {
+    height: 100vh;
+    position: relative;
+
+    // 固定区域样式
+    .fixed-header {
+      position: fixed;
+      top: 0;
+      left: 0;
+      right: 0;
+      z-index: 100;
+      background-color: $background-color-light;
+    }
+
+    .game-header {
+      position: relative;
+      width: 100%;
+      height: 150px; // 限制高度为150px
+
+      .game-image {
+        width: 100%;
+        height: 100%;
+        object-fit: cover;
+        object-position: top; // 图片从顶部对齐
+      }
+
+      &__overlay {
+        position: absolute;
+        bottom: 0;
+        left: 0;
+        right: 0;
+        padding: $spacing-medium;
+        background: linear-gradient(to top, rgba(0,0,0,0.8), rgba(0,0,0,0.4) 80%, rgba(0,0,0,0));
+
+        .game-title {
+          font-size: $font-size-large;
+          font-weight: $font-weight-bold;
+          color: $text-color-light;
+          margin-bottom: $spacing-mini;
+        }
+
+        .game-stats {
+          display: flex;
+          align-items: center;
+
+          .game-players, .game-duration {
+            display: flex;
+            align-items: center;
+            margin-right: $spacing-medium;
+            color: $text-color-light;
+            font-size: $font-size-small;
+
+            text {
+              margin-left: $spacing-mini;
+            }
+          }
+        }
+      }
+    }
+
+    // 评分区域
+    .game-rating-section {
+      padding: $spacing-base $spacing-large;
+      background-color: $background-color-light;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      border-bottom: 1px solid $border-color-light;
+
+      .rating-score {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+
+        .score {
+          font-size: $font-size-xlarge;
+          font-weight: $font-weight-bold;
+          color: $text-color-primary;
+          line-height: 1.2;
+        }
+      }
+
+      .rating-stats {
+        display: flex;
+
+        .rating-item {
+          margin-left: $spacing-large;
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+
+          .value {
+            font-size: $font-size-large;
+            font-weight: $font-weight-medium;
+            color: $primary-color;
+          }
+
+          .label {
+            font-size: $font-size-mini;
+            color: $text-color-secondary;
+            margin-top: $spacing-mini;
+          }
+        }
+      }
+    }
+
+    // 操作按钮区域
+    .game-actions {
+      display: flex;
+      padding: $spacing-medium;
+      background-color: $background-color-light;
+
+      .action-btn-container {
+        flex: 1;
+        padding: 0 $spacing-mini;
+
+        &:first-child {
+          padding-left: 0;
+        }
+
+        &:last-child {
+          padding-right: 0;
+        }
+
+        .action-btn {
+          width: 100%;
+        }
+      }
+    }
+
+    // 内容区域
+    .content-scroll-view {
+      height: 100vh;
+      /* 增加padding-top确保第一个divider不被遮挡 */
+      padding-top: 230px;
+      box-sizing: border-box;
+      background-color: $background-color-base;
+
+      .scrollable-content {
+        background-color: $background-color-light;
+      }
+
+      /* 添加顶部间距确保第一个divider可见 */
+      .top-padding {
+        height: 12px; /* 增加一点额外空间 */
+      }
+
+      .section-container {
+        padding: 0 $spacing-large $spacing-small;
+
+        /* 确保内容区有最小高度,防止没有内容时布局错乱 */
+        min-height: 40px;
+      }
+
+      .section-content {
+        font-size: $font-size-base;
+        color: $text-color-regular;
+        line-height: $line-height-base;
+        white-space: pre-line;
+
+        /* 处理超长单词换行 */
+        word-wrap: break-word;
+        word-break: break-all;
+      }
+
+      .tip-list {
+        .tip-item {
+          display: flex;
+          margin-bottom: $spacing-small;
+
+          .tip-number {
+            font-weight: $font-weight-medium;
+            color: $text-color-primary;
+            margin-right: $spacing-small;
+            flex-shrink: 0; /* 防止数字被压缩 */
+          }
+
+          .tip-content {
+            color: $text-color-regular;
+            flex: 1;
+            word-wrap: break-word; /* 确保长文本能正确换行 */
+          }
+        }
+      }
+
+      .example-item {
+        margin-bottom: $spacing-medium;
+        padding: $spacing-medium;
+        border-radius: $border-radius-small;
+        background-color: $background-color-gray;
+
+        &:last-child {
+          margin-bottom: 0;
+        }
+
+        .example-question, .example-answer {
+          margin-bottom: $spacing-small;
+
+          &:last-child {
+            margin-bottom: 0;
+          }
+
+          .example-label {
+            font-weight: $font-weight-medium;
+            color: $text-color-primary;
+            margin-right: $spacing-mini;
+            display: inline-block; /* 确保label和内容能够适当排列 */
+          }
+        }
+      }
+    }
+  }
+
+  .loading-container {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    height: 200px;
+
+    text {
+      margin-top: $spacing-small;
+      font-size: $font-size-small;
+      color: $text-color-secondary;
+    }
+  }
+}
+
+// 自定义 divider 样式,使其更紧凑
+:deep(.nut-divider) {
+  margin: $spacing-small 0 !important;
+  font-size: $font-size-base !important;
+  font-weight: $font-weight-medium !important;
+}
 </style>

+ 9 - 9
src/pages/index/index.vue

@@ -17,7 +17,7 @@
               :id="game.id"
               :title="game.title"
               :image="game.image"
-              :players="game.players"
+              :players="game.minPlayers + '-' + game.maxPlayers"
               :duration="game.duration"
               :rating="game.rating"
               :is-new="game.isNew"
@@ -35,7 +35,7 @@
               :id="game.id"
               :title="game.title"
               :image="game.image"
-              :players="game.players"
+                :players="game.minPlayers + '-' + game.maxPlayers"
               :duration="game.duration"
               :rating="game.rating"
               :is-new="game.isNew"
@@ -53,7 +53,7 @@
               :id="game.id"
               :title="game.title"
               :image="game.image"
-              :players="game.players"
+              :players="game.minPlayers + '-' + game.maxPlayers"
               :duration="game.duration"
               :rating="game.rating"
               :is-new="game.isNew"
@@ -71,7 +71,7 @@
               :id="game.id"
               :title="game.title"
               :image="game.image"
-              :players="game.players"
+              :players="game.minPlayers + '-' + game.maxPlayers"
               :duration="game.duration"
               :rating="game.rating"
               :is-new="game.isNew"
@@ -101,7 +101,7 @@
               :id="game.id"
               :title="game.title"
               :image="game.image"
-              :players="game.players"
+              :players="game.minPlayers + '-' + game.maxPlayers"
               :duration="game.duration"
               :rating="game.rating"
               :is-new="game.isNew"
@@ -120,7 +120,7 @@
               :id="game.id"
               :title="game.title"
               :image="game.image"
-              :players="game.players"
+              :players="game.minPlayers + '-' + game.maxPlayers"
               :duration="game.duration"
               :rating="game.rating"
               :is-new="game.isNew"
@@ -139,7 +139,7 @@
               :id="game.id"
               :title="game.title"
               :image="game.image"
-              :players="game.players"
+              :players="game.minPlayers + '-' + game.maxPlayers"
               :duration="game.duration"
               :rating="game.rating"
               :is-new="game.isNew"
@@ -158,7 +158,7 @@
               :id="game.id"
               :title="game.title"
               :image="game.image"
-              :players="game.players"
+              :players="game.minPlayers + '-' + game.maxPlayers"
               :duration="game.duration"
               :rating="game.rating"
               :is-new="game.isNew"
@@ -290,7 +290,7 @@ export default {
     // 社交游戏
     const socialGames = computed(() => {
       return gameStore.games.filter(game => {
-        const maxPlayers = parseInt(game.players.split('-')[1] || game.players)
+        const maxPlayers = parseInt(game.minPlayers.toString() + '-' + game.maxPlayers.toString())
         return maxPlayers >= 6
       })
     })

+ 51 - 38
src/pages/room/create/index.vue

@@ -6,7 +6,7 @@
         <view class="game-detail">
           <view class="game-title">{{ gameInfo.title }}</view>
           <view class="game-meta">
-            <text>{{ gameInfo.players }}人</text>
+            <text>{{ gameInfo.minPlayers }}人-{{ gameInfo.maxPlayers }}人</text>
             <text>{{ gameInfo.duration }}分钟</text>
           </view>
         </view>
@@ -27,10 +27,17 @@
         <view class="random-name" @click="generateRandomName">随机名称</view>
       </view>
       
-      <view class="setting-item">
+      <view class="setting-item" v-if="gameInfo">
         <view class="setting-label">最大人数</view>
         <view class="setting-slider">
-          <nut-range v-model="maxPlayers" :min="2" :max="12" inactive-color="#E5E5E5" button-color="#3C92FB" active-color="#3C92FB"></nut-range>
+          <nut-range 
+            v-model="maxPlayers" 
+            :min="gameInfo.minPlayers" 
+            :max="gameInfo.maxPlayers" 
+            inactive-color="#E5E5E5" 
+            button-color="#3C92FB" 
+            active-color="#3C92FB">
+          </nut-range>
           <view class="slider-value">{{ maxPlayers }}人</view>
         </view>
       </view>
@@ -95,7 +102,7 @@ export default {
 
     // 房间设置
     const roomName = ref('')
-    const maxPlayers = ref(6)
+    const maxPlayers = ref(0) // 初始值会在游戏加载后设置
     const roomVisibility = ref('private')
     const roomPassword = ref('')
 
@@ -133,14 +140,8 @@ export default {
           // 设置默认房间名
           roomName.value = `${game.title}房间`
           
-          // 从游戏的人数范围设置最大人数
-          const playersRange = game.players.split('-')
-          if (playersRange.length > 1) {
-            const max = parseInt(playersRange[1])
-            if (!isNaN(max)) {
-              maxPlayers.value = Math.min(max, 12) // 限制最大12人
-            }
-          }
+          // 设置最大人数默认值为游戏的最大人数
+          maxPlayers.value = game.maxPlayers
         }
       } catch (error) {
         console.error('获取游戏信息失败:', error)
@@ -169,34 +170,46 @@ export default {
         return
       }
       
-      try {
-    Taro.showLoading({ title: '创建房间中...' })
-    
-    // 构建房间数据 - 不需要包含用户信息,store内部会处理
-    const roomData = {
-      id: `room_${Date.now()}_${Math.floor(Math.random() * 1000)}`,
-      name: roomName.value,
-      gameId: gameInfo.value?.id || '',
-      gameTitle: gameInfo.value?.title || '',
-      maxPlayers: maxPlayers.value,
-      visibility: roomVisibility.value as RoomVisibility,
-      password: roomVisibility.value === 'private' ? roomPassword.value : undefined,
-      hosterId: userStore.openid,
-      createTime: Date.now(),
-      status: RoomStatus.WAITING,
-      users: [] // 空数组,store内部会添加主持人信息
-    }
-    
-    const result = await roomStore.createRoom(roomData)
-    
-    if (result.success && result.roomId) {
-      // 导航到房间页面
-        roomStore.navigateToRoomPage(result.roomId)
-      } else {
-        throw new Error(result.message || '创建房间失败')
+      if (!gameInfo.value) {
+        Taro.showToast({
+          title: '游戏信息不存在',
+          icon: 'none'
+        })
+        return
       }
+      
+      try {
+        Taro.showLoading({ title: '创建房间中...' })
+        
+        // 构建房间数据 - 使用滑块选择的最大人数
+        const roomData = {
+          id: `room_${Date.now()}_${Math.floor(Math.random() * 1000)}`,
+          name: roomName.value,
+          gameId: gameInfo.value.id || '',
+          gameTitle: gameInfo.value.title || '',
+          maxPlayers: maxPlayers.value, // 使用滑块选择的人数
+          visibility: roomVisibility.value as RoomVisibility,
+          password: roomVisibility.value === 'private' ? roomPassword.value : undefined,
+          hosterId: userStore.openid,
+          createTime: Date.now(),
+          status: RoomStatus.WAITING,
+          users: [] // 空数组,store内部会添加主持人信息
+        }
+        
+        const result = await roomStore.createRoom(roomData)
+        
+        if (result.success && result.roomId) {
+          // 导航到房间页面
+          roomStore.navigateToRoomPage(result.roomId)
+        } else {
+          throw new Error(result.message || '创建房间失败')
+        }
       } catch (error) {
-        // 错误处理...
+        console.error('创建房间失败:', error)
+        Taro.showToast({
+          title: error instanceof Error ? error.message : '创建房间失败',
+          icon: 'none'
+        })
       } finally {
         Taro.hideLoading()
       }

+ 6 - 3
src/services/game.ts

@@ -10,7 +10,8 @@ const mockGames: Game[] = [
     id: '1',
     title: '海龟汤',
     image: 'https://images.unsplash.com/photo-1582845512747-e42001c95638?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&h=100&q=80',
-    players: '3-10',
+    minPlayers: 3,
+    maxPlayers: 10,
     duration: '30-60',
     rating: 4.8,
     isNew: true,
@@ -36,7 +37,8 @@ const mockGames: Game[] = [
     id: '2',
     title: '剧本杀',
     image: 'https://images.unsplash.com/photo-1529156069898-49953e39b3ac?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&h=100&q=80',
-    players: '4-8',
+    minPlayers: 4,
+    maxPlayers: 8,
     duration: '120-180',
     rating: 4.5,
     isNew: false,
@@ -62,7 +64,8 @@ const mockGames: Game[] = [
     id: '3',
     title: '狼人杀',
     image: 'https://images.unsplash.com/photo-1529156069898-49953e39b3ac?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&h=100&q=80',
-    players: '6-12',
+    minPlayers: 6,
+    maxPlayers: 12,
     duration: '30-45',
     rating: 4.7,
     isNew: false,

+ 2 - 1
src/types/game.ts

@@ -3,7 +3,8 @@ export interface Game {
     id: string; // 游戏ID
     title: string; // 游戏标题
     image: string; // 游戏图片
-    players: string; // 游戏人数
+    minPlayers: number; // 最小玩家人数
+    maxPlayers: number; // 最大玩家人数
     duration: string; // 游戏时长
     rating: number; // 游戏评分
     isNew: boolean; // 是否为新游戏