feat: 数据mock

This commit is contained in:
2026-06-18 13:10:09 +08:00
parent deae38fb05
commit 9bd85a4e43
15 changed files with 466 additions and 403 deletions

View File

@@ -37,61 +37,47 @@
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { ref, computed, onMounted } from 'vue'
import { useBaseLayoutStore } from '@/stores'
import { storeToRefs } from 'pinia'
import { getGameList, type GameItem } from '@/api/modules/game'
/** 游戏数据接口 */
interface GameInfo {
id: string
/** 图标emoji 或文字占位) */
icon: string
name: string
description: string
gameplay: string
/** 游戏列表 */
const games = ref<GameItem[]>([])
/** 加载状态 */
const loading = ref<boolean>(false)
/** 获取游戏列表 */
async function fetchGameList() {
loading.value = true
try {
const res = await getGameList()
games.value = res.data.list
// 默认选中第一个游戏
if (games.value.length > 0 && !activeGameId.value) {
const first = games.value[0]
if (first) {
baseLayoutStore.setActiveGame(first.id, first.icon, first.name)
}
}
} finally {
loading.value = false
}
}
/** 游戏列表数据 */
const games: GameInfo[] = [
{
id: 'snake',
icon: '🐍',
name: '贪吃蛇',
description: '经典贪吃蛇竞技,在狭小空间内争夺生存权',
gameplay: '方向键控制蛇的移动,吃到食物变长。撞墙或其他蛇的身体即死亡,最后存活的玩家获胜。'
},
{
id: 'tetris',
icon: '🧊',
name: '俄罗斯方块',
description: '经典下落消除,与对手一较高下',
gameplay: '方向键移动和旋转方块,填满横排即可消除。同时向对手发送干扰行,坚持到最后的玩家获胜。'
},
{
id: 'gomoku',
icon: '⚫',
name: '五子棋',
description: '黑白对弈,先连成五子者胜',
gameplay: '鼠标点击落子,黑白双方轮流在棋盘上放置棋子。先在横、竖、斜任意方向连成五子的一方获胜。'
},
{
id: 'guess-number',
icon: '🔢',
name: '猜数字',
description: '逻辑推理对战,猜中对方的秘密数字',
gameplay: '每轮输入猜测的数字组合,系统会提示位置和数字正确的数量。率先猜中对手数字组合的玩家获胜。'
}
]
onMounted(() => {
fetchGameList()
})
const baseLayoutStore = useBaseLayoutStore()
const { activeGameId } = storeToRefs(baseLayoutStore)
/** 当前选中的游戏对象 */
const activeGame = computed(() => games.find((g) => g.id === activeGameId.value) ?? null)
const activeGame = computed(() => games.value.find((g) => g.id === activeGameId.value) ?? null)
/** 选择游戏 */
function selectGame(id: string) {
const game = games.find((g) => g.id === id)
const game = games.value.find((g) => g.id === id)
if (game) {
baseLayoutStore.setActiveGame(game.id, game.icon, game.name)
}

View File

@@ -43,9 +43,10 @@
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import TableCard from './TableCard.vue'
import type { Room } from './TableCard.vue'
import type { RoomItem } from '@/api/modules/game'
import { useBaseLayoutStore } from '@/stores'
import { storeToRefs } from 'pinia'
import { getRoomList } from '@/api/modules/game'
/** 状态筛选选项 */
const statusFilters = [
@@ -58,336 +59,30 @@ const activeFilter = ref('all')
const baseLayoutStore = useBaseLayoutStore()
const { activeGameId } = storeToRefs(baseLayoutStore)
/** 切换游戏时重置筛选 */
/** 房间列表 */
const rooms = ref<RoomItem[]>([])
/** 加载状态 */
const loading = ref<boolean>(false)
/** 获取房间列表 */
async function fetchRoomList() {
loading.value = true
try {
const res = await getRoomList({ gameId: activeGameId.value })
rooms.value = res.data.list
} finally {
loading.value = false
}
}
/** 切换游戏时重新获取房间列表并重置筛选 */
watch(activeGameId, () => {
activeFilter.value = 'all'
fetchRoomList()
})
/** 根据名字生成头像 URL */
function avatarUrl(name: string): string {
return `https://api.dicebear.com/7.x/bottts-neutral/svg?seed=${encodeURIComponent(name)}`
}
/**
* 各游戏的模拟房间数据
* key 对应 GameList 中的 gameId
*/
const ALL_ROOMS: Record<string, Room[]> = {
/* ---- 贪吃蛇 ---- */
snake: [
{
id: 'snake-001',
name: '桌 01',
gameIcon: '🐍',
gameId: 'snake',
maxPlayers: 4,
players: [
{ avatar: avatarUrl('小龙'), nickname: '小龙' },
{ avatar: avatarUrl('阿蟒'), nickname: '阿蟒' }
],
status: 'waiting',
statusText: '等待中',
stakes: 300,
mode: '经典模式',
creatorName: '小龙'
},
{
id: 'snake-002',
name: '桌 02',
gameIcon: '🐍',
gameId: 'snake',
maxPlayers: 4,
players: [
{ avatar: avatarUrl('闪电'), nickname: '闪电' },
{ avatar: avatarUrl('疾风'), nickname: '疾风' },
{ avatar: avatarUrl('游侠'), nickname: '游侠' },
{ avatar: avatarUrl('幻影'), nickname: '幻影' }
],
status: 'playing',
statusText: '进行中',
stakes: 500,
mode: '道具模式',
creatorName: '闪电'
},
{
id: 'snake-003',
name: '桌 03',
gameIcon: '🐍',
gameId: 'snake',
maxPlayers: 4,
players: [{ avatar: avatarUrl('青蛇'), nickname: '青蛇' }],
status: 'waiting',
statusText: '等待中',
stakes: 200,
mode: '加速模式',
creatorName: '青蛇'
},
{
id: 'snake-004',
name: '桌 04',
gameIcon: '🐍',
gameId: 'snake',
maxPlayers: 4,
players: [],
status: 'waiting',
statusText: '等待中',
stakes: 100,
mode: '经典模式',
creatorName: '毒牙'
},
{
id: 'snake-005',
name: '桌 05',
gameIcon: '🐍',
gameId: 'snake',
maxPlayers: 4,
players: [
{ avatar: avatarUrl('巨蟒'), nickname: '巨蟒' },
{ avatar: avatarUrl('灵蛇'), nickname: '灵蛇' },
{ avatar: avatarUrl('毒牙'), nickname: '毒牙' }
],
status: 'waiting',
statusText: '等待中',
stakes: 400,
mode: '道具模式',
creatorName: '巨蟒'
}
],
/* ---- 俄罗斯方块 ---- */
tetris: [
{
id: 'tetris-001',
name: '桌 01',
gameIcon: '🧊',
gameId: 'tetris',
maxPlayers: 2,
players: [{ avatar: avatarUrl('方块大师'), nickname: '方块大师' }],
status: 'waiting',
statusText: '等待中',
stakes: 300,
mode: '1v1 对战',
creatorName: '方块大师'
},
{
id: 'tetris-002',
name: '桌 02',
gameIcon: '🧊',
gameId: 'tetris',
maxPlayers: 2,
players: [
{ avatar: avatarUrl('极速下落'), nickname: '极速下落' },
{ avatar: avatarUrl('消行高手'), nickname: '消行高手' }
],
status: 'playing',
statusText: '进行中',
stakes: 500,
mode: '竞速模式',
creatorName: '极速下落'
},
{
id: 'tetris-003',
name: '桌 03',
gameIcon: '🧊',
gameId: 'tetris',
maxPlayers: 2,
players: [],
status: 'waiting',
statusText: '等待中',
stakes: 150,
mode: '1v1 对战',
creatorName: '堆叠王者'
},
{
id: 'tetris-004',
name: '桌 04',
gameIcon: '🧊',
gameId: 'tetris',
maxPlayers: 2,
players: [{ avatar: avatarUrl('T旋大师'), nickname: 'T旋大师' }],
status: 'waiting',
statusText: '等待中',
stakes: 200,
mode: '1v1 对战',
creatorName: 'T旋大师'
},
{
id: 'tetris-005',
name: '桌 05',
gameIcon: '🧊',
gameId: 'tetris',
maxPlayers: 2,
players: [
{ avatar: avatarUrl('连击王'), nickname: '连击王' },
{ avatar: avatarUrl('消除者'), nickname: '消除者' }
],
status: 'playing',
statusText: '进行中',
stakes: 400,
mode: '竞速模式',
creatorName: '连击王'
}
],
/* ---- 五子棋 ---- */
gomoku: [
{
id: 'gomoku-001',
name: '桌 01',
gameIcon: '⚫',
gameId: 'gomoku',
maxPlayers: 2,
players: [{ avatar: avatarUrl('棋圣'), nickname: '棋圣' }],
status: 'waiting',
statusText: '等待中',
stakes: 200,
mode: '无禁手',
creatorName: '棋圣'
},
{
id: 'gomoku-002',
name: '桌 02',
gameIcon: '⚫',
gameId: 'gomoku',
maxPlayers: 2,
players: [
{ avatar: avatarUrl('黑白子'), nickname: '黑白子' },
{ avatar: avatarUrl('五连珠'), nickname: '五连珠' }
],
status: 'playing',
statusText: '进行中',
stakes: 400,
mode: '有禁手',
creatorName: '黑白子'
},
{
id: 'gomoku-003',
name: '桌 03',
gameIcon: '⚫',
gameId: 'gomoku',
maxPlayers: 2,
players: [],
status: 'waiting',
statusText: '等待中',
stakes: 100,
mode: '无禁手',
creatorName: '落子无悔'
},
{
id: 'gomoku-004',
name: '桌 04',
gameIcon: '⚫',
gameId: 'gomoku',
maxPlayers: 2,
players: [{ avatar: avatarUrl('天元'), nickname: '天元' }],
status: 'waiting',
statusText: '等待中',
stakes: 300,
mode: '有禁手',
creatorName: '天元'
},
{
id: 'gomoku-005',
name: '桌 05',
gameIcon: '⚫',
gameId: 'gomoku',
maxPlayers: 2,
players: [
{ avatar: avatarUrl('先手必胜'), nickname: '先手必胜' },
{ avatar: avatarUrl('后手无敌'), nickname: '后手无敌' }
],
status: 'playing',
statusText: '进行中',
stakes: 500,
mode: '有禁手',
creatorName: '先手必胜'
}
],
/* ---- 猜数字 ---- */
'guess-number': [
{
id: 'guess-001',
name: '桌 01',
gameIcon: '🔢',
gameId: 'guess-number',
maxPlayers: 4,
players: [
{ avatar: avatarUrl('逻辑怪'), nickname: '逻辑怪' },
{ avatar: avatarUrl('推理王'), nickname: '推理王' }
],
status: 'waiting',
statusText: '等待中',
stakes: 200,
mode: '经典模式',
creatorName: '逻辑怪'
},
{
id: 'guess-002',
name: '桌 02',
gameIcon: '🔢',
gameId: 'guess-number',
maxPlayers: 4,
players: [
{ avatar: avatarUrl('秒猜'), nickname: '秒猜' },
{ avatar: avatarUrl('心算'), nickname: '心算' },
{ avatar: avatarUrl('直觉'), nickname: '直觉' }
],
status: 'waiting',
statusText: '等待中',
stakes: 300,
mode: '限时模式',
creatorName: '秒猜'
},
{
id: 'guess-003',
name: '桌 03',
gameIcon: '🔢',
gameId: 'guess-number',
maxPlayers: 4,
players: [{ avatar: avatarUrl('数字猎人'), nickname: '数字猎人' }],
status: 'waiting',
statusText: '等待中',
stakes: 150,
mode: '经典模式',
creatorName: '数字猎人'
},
{
id: 'guess-004',
name: '桌 04',
gameIcon: '🔢',
gameId: 'guess-number',
maxPlayers: 4,
players: [
{ avatar: avatarUrl('密码破解'), nickname: '密码破解' },
{ avatar: avatarUrl('枚举大师'), nickname: '枚举大师' },
{ avatar: avatarUrl('二分法'), nickname: '二分法' },
{ avatar: avatarUrl('穷举王'), nickname: '穷举王' }
],
status: 'playing',
statusText: '进行中',
stakes: 500,
mode: '限时模式',
creatorName: '密码破解'
},
{
id: 'guess-005',
name: '桌 05',
gameIcon: '🔢',
gameId: 'guess-number',
maxPlayers: 4,
players: [],
status: 'waiting',
statusText: '等待中',
stakes: 100,
mode: '经典模式',
creatorName: '神秘数字'
}
]
}
/** 当前游戏的房间列表 */
const rooms = computed(() => ALL_ROOMS[activeGameId.value] ?? [])
/** 首次加载 */
fetchRoomList()
/** 筛选后的房间列表 */
const filteredRooms = computed(() => {

View File

@@ -72,40 +72,10 @@
<script setup lang="ts">
import { computed } from 'vue'
/** 房间内玩家 */
interface RoomPlayer {
avatar: string
nickname: string
}
/** 房间数据 */
export interface Room {
id: string
/** 桌号显示名,如 "桌 01" */
name: string
/** 游戏图标 emoji */
gameIcon: string
/** 游戏 ID */
gameId: string
/** 最大玩家数 */
maxPlayers: number
/** 已入座玩家列表 */
players: RoomPlayer[]
/** 房间状态 */
status: 'waiting' | 'playing' | 'finished'
/** 状态展示文字 */
statusText: string
/** 底注金额 */
stakes: number
/** 玩法模式标签 */
mode: string
/** 房主昵称 */
creatorName: string
}
import type { RoomItem, RoomPlayer, RoomStatus } from '@/api/modules/game'
const props = defineProps<{
room: Room
room: RoomItem
}>()
const emit = defineEmits<{