97 lines
2.2 KiB
Vue
97 lines
2.2 KiB
Vue
|
|
<template>
|
||
|
|
<Card :clickable="clickable" @click="handleClick" hoverable>
|
||
|
|
<div class="game-cover">
|
||
|
|
<img :src="game.coverUrl || 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'" :alt="game.name" />
|
||
|
|
<div class="game-overlay">
|
||
|
|
<el-button type="primary" size="small">查看详情</el-button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="game-content">
|
||
|
|
<div v-if="showTags && game.tags?.length" class="game-tags">
|
||
|
|
<el-tag
|
||
|
|
v-for="tag in game.tags"
|
||
|
|
:key="tag"
|
||
|
|
size="small"
|
||
|
|
:type="getGameTagType(tag)"
|
||
|
|
>
|
||
|
|
{{ tag }}
|
||
|
|
</el-tag>
|
||
|
|
</div>
|
||
|
|
<h4 class="game-title">{{ game.name }}</h4>
|
||
|
|
<p class="game-players">
|
||
|
|
<el-icon><User /></el-icon>
|
||
|
|
{{ game.minPlayers }}-{{ game.maxPlayers }}人
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</Card>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup lang="ts">
|
||
|
|
import type { GameInfo } from '@/types/game'
|
||
|
|
import Card from '@/components/common/Card/Card.vue'
|
||
|
|
import { User } from '@element-plus/icons-vue'
|
||
|
|
|
||
|
|
interface Props {
|
||
|
|
game: GameInfo
|
||
|
|
clickable?: boolean
|
||
|
|
showTags?: boolean
|
||
|
|
}
|
||
|
|
|
||
|
|
const props = withDefaults(defineProps<Props>(), {
|
||
|
|
clickable: true,
|
||
|
|
showTags: true
|
||
|
|
})
|
||
|
|
|
||
|
|
const emit = defineEmits<{
|
||
|
|
click: [game: GameInfo]
|
||
|
|
}>()
|
||
|
|
|
||
|
|
const getGameTagType = (tag: string) => {
|
||
|
|
const typeMap: Record<string, any> = {
|
||
|
|
'MOBA': 'danger',
|
||
|
|
'FPS': 'warning',
|
||
|
|
'RPG': 'success',
|
||
|
|
'策略': 'primary'
|
||
|
|
}
|
||
|
|
return typeMap[tag] || 'info'
|
||
|
|
}
|
||
|
|
|
||
|
|
const handleClick = () => {
|
||
|
|
if (props.clickable) {
|
||
|
|
emit('click', props.game)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped lang="scss">
|
||
|
|
.game-cover {
|
||
|
|
@apply relative rounded-lg overflow-hidden -mx-6 -mt-6 mb-4;
|
||
|
|
height: 180px;
|
||
|
|
|
||
|
|
img {
|
||
|
|
@apply w-full h-full object-cover;
|
||
|
|
}
|
||
|
|
|
||
|
|
.game-overlay {
|
||
|
|
@apply absolute inset-0 bg-black/50 flex items-center justify-center opacity-0 transition-opacity duration-200;
|
||
|
|
|
||
|
|
&:hover {
|
||
|
|
@apply opacity-100;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.game-tags {
|
||
|
|
@apply flex gap-2 mb-2;
|
||
|
|
}
|
||
|
|
|
||
|
|
.game-title {
|
||
|
|
@apply text-lg font-semibold text-gray-900 mb-2;
|
||
|
|
}
|
||
|
|
|
||
|
|
.game-players {
|
||
|
|
@apply text-sm text-gray-500 flex items-center gap-1;
|
||
|
|
}
|
||
|
|
</style>
|