mahjong_group/components/index/MahjongCard.vue
2025-09-10 23:11:48 +08:00

333 lines
7.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="grid" @click="handleCardClick">
<view class="grid-item">
<view style="height: 251rpx;">
<view class="nine-grid-container">
<view></view>
<view class="item">
<view class="item-avatar">
<image src="@@:app/static/add.png" class="avatar-img" mode="aspectFit">
</image>
</view>
</view>
<view></view>
<view class="item">
<view class="item-avatar">
<image src="@@:app/static/add.png" class="avatar-img" mode="aspectFit">
</image>
</view>
</view>
<view></view>
<view class="item">
<view class="item-avatar">
<image src="@@:app/static/add.png" class="avatar-img" mode="aspectFit">
</image>
</view>
</view>
<view></view>
<view class="item">
<view class="item-avatar">
<image src="@@:app/static/add.png" class="avatar-img" mode="aspectFit">
</image>
</view>
</view>
<view></view>
</view>
</view>
<view style="width: 100%;display: flex;align-items: center;justify-content: center;">
<view style="width: 90%;">
<view
style="color: #000000;font-family: PingFang SC, PingFang SC;font-weight: 500;font-size: 28rpx;text-align: left;font-style: normal;text-transform: none;">
{{item.description}}
</view>
<view
style="font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 18rpx;color: #575757;text-align: left;font-style: normal;text-transform: none;">
{{item.time}}
</view>
<view
style="font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 18rpx;color: #575757;text-align: left;font-style: normal;text-transform: none;">
{{item.room}}
</view>
<view
style="font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 18rpx;color: #575757;text-align: left;font-style: normal;text-transform: none;">
{{item.requirements}}
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import {
defineProps,
defineEmits,
computed
} from 'vue'
// 定义 props
const props = defineProps({
item: {
type: Object,
required: true,
default: () => ({
id: '',
status: '',
description: '',
time: '',
room: '',
requirements: '',
personCount: 4, //总人数
joinPerson: [{
id: 1,
name: '张三',
avatar: '',
phone: '',
}], //已加入人
})
}
})
// 定义 emits
const emit = defineEmits(['click', 'join'])
// 计算属性:获取玩家位置布局
const playerPositions = computed(() => {
const {
personCount,
joinPerson
} = props.item
const joinedCount = joinPerson.length
// 根据总人数确定布局
if (personCount === 2) {
// 2人局第二行左边和右边
return {
positions: [null, joinPerson[0] || null, joinPerson[1] || null, null],
joinPositions: [null, !joinPerson[0], !joinPerson[1], null]
}
} else if (personCount === 3) {
// 3人局第一行中间、第二行左边和右边
return {
positions: [joinPerson[2] || null, joinPerson[0] || null, joinPerson[1] || null, null],
joinPositions: [!joinPerson[2], !joinPerson[0], !joinPerson[1], null]
}
} else {
// 4人局标准布局上、左、右、下
return {
positions: [
joinPerson[2] || null, // 第一行中间
joinPerson[0] || null, // 第二行左边
joinPerson[1] || null, // 第二行右边
joinPerson[3] || null // 第三行中间
],
joinPositions: [
!joinPerson[2], // 第一行中间
!joinPerson[0], // 第二行左边
!joinPerson[1], // 第二行右边
!joinPerson[3] // 第三行中间
]
}
}
})
// 获取指定位置的玩家
const getPlayerAtPosition = (position) => {
return playerPositions.value.positions[position]
}
// 判断指定位置是否可以加入
const canJoinAtPosition = (position) => {
const {
personCount,
joinPerson
} = props.item
const joinedCount = joinPerson.length
// 如果已满员,不能加入
if (joinedCount >= personCount) {
return false
}
// 直接使用计算属性中的 joinPositions
return playerPositions.value.joinPositions[position]
}
// 获取单元格样式类
const getCellClass = (position) => {
if (getPlayerAtPosition(position)) {
return 'player-cell'
} else if (canJoinAtPosition(position)) {
return 'join-cell'
}
return ''
}
// 处理卡片点击事件
const handleCardClick = () => {
emit('click', props.item)
}
// 处理加入按钮点击事件
const handleJoin = () => {
emit('join', props.item)
}
</script>
<style lang="scss" scoped>
.grid {
width: 100%;
display: flex;
align-content: center;
justify-content: center;
}
.grid-item {
width: 320rpx;
height: 400rpx;
background: #FFFFFF;
box-shadow: -4rpx 12rpx 7rpx 0rpx rgba(0, 0, 0, 0.25);
border-radius: 27rpx 27rpx 27rpx 27rpx;
border: 4rpx solid #006C1A
}
.item-content {
height: 540rpx;
color: white;
border-radius: 10rpx;
font-size: 32rpx;
}
.item {
display: flex;
align-content: center;
justify-content: center;
align-items: center;
}
.item-avatar {
width: 60rpx;
height: 60rpx;
background-color: #60AA72;
border-radius: 50rpx;
}
.mahjong-table {
width: 100%;
background-color: #D4D4D4;
border-radius: 10rpx 10rpx 0 0;
display: flex;
justify-content: center;
}
.status-tag {
position: absolute;
left: 15rpx;
top: 15rpx;
font-size: 16rpx;
color: black;
z-index: 10;
}
/* 九宫格容器 */
.nine-grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
width: 100%;
height: 100%;
box-sizing: border-box;
background: url('@@:app/static/index_logo.png') no-repeat center center;
background-size: 50%;
}
/* 网格单元格 */
.grid-cell {
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
/* 玩家头像单元格 */
.player-cell {
display: flex;
align-items: center;
justify-content: center;
}
/* 中心单元格(麻将桌) */
.center-cell {
display: flex;
align-items: center;
justify-content: center;
}
/* 加入按钮单元格 */
.join-cell {
display: flex;
align-items: center;
justify-content: center;
}
/* 麻将桌背景图 */
.table-bg {
width: 80rpx;
height: 80rpx;
}
/* 玩家头像 */
.player-avatar {
width: 60rpx;
height: 60rpx;
background-color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.avatar-img {
border-radius: 50%;
width: 60rpx;
height: 60rpx;
}
/* 加入按钮 */
.join-button {
width: 60rpx;
height: 60rpx;
background-color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.3s ease;
}
.join-button:hover {
transform: scale(1.1);
background-color: #f0f0f0;
}
.join-text {
color: black;
font-size: 24rpx;
font-weight: bold;
}
.info-section {
padding: 10rpx;
}
.info-text {
font-size: 24rpx;
color: black;
display: block;
}
</style>