feat(game): 实现麻将手牌按花色分组显示功能
- 添加 HandSuitLabel 类型定义区分万筒条三种花色 - 创建手牌花色排序映射和标签映射配置 - 实现 visibleHandTileGroups 计算属性按花色对手牌进行分组 - 新增 player-hand-group 样式类支持分组布局 - 调整 tile-chip 尺寸适配新的分组显示方式 - 修改底部控制面板位置避免遮挡手牌区域
This commit is contained in:
@@ -807,7 +807,7 @@
|
|||||||
.bottom-control-panel {
|
.bottom-control-panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
bottom: 8px;
|
bottom: 100px;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: min(100% - 120px, 1180px);
|
width: min(100% - 120px, 1180px);
|
||||||
padding: 8px 14px 12px;
|
padding: 8px 14px 12px;
|
||||||
@@ -880,17 +880,24 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 4px;
|
gap: 12px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.player-hand-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
gap: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.tile-chip {
|
.tile-chip {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-width: 90px;
|
min-width: 74px;
|
||||||
height: 126px;
|
height: 104px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
@@ -1083,8 +1090,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tile-chip {
|
.tile-chip {
|
||||||
min-width: 70px;
|
min-width: 60px;
|
||||||
height: 102px;
|
height: 88px;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1160,8 +1167,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tile-chip {
|
.tile-chip {
|
||||||
min-width: 48px;
|
min-width: 42px;
|
||||||
height: 76px;
|
height: 64px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ type DisplayPlayer = PlayerState & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GameActionPayload<TType extends GameAction['type']> = Extract<GameAction, { type: TType }>['payload']
|
type GameActionPayload<TType extends GameAction['type']> = Extract<GameAction, { type: TType }>['payload']
|
||||||
|
type HandSuitLabel = '万' | '筒' | '条'
|
||||||
|
|
||||||
interface SeatViewModel {
|
interface SeatViewModel {
|
||||||
key: SeatKey
|
key: SeatKey
|
||||||
@@ -132,6 +133,51 @@ const myHandTiles = computed(() => {
|
|||||||
return myPlayer.value?.handTiles ?? []
|
return myPlayer.value?.handTiles ?? []
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const handSuitOrder: Record<Tile['suit'], number> = {
|
||||||
|
W: 0,
|
||||||
|
T: 1,
|
||||||
|
B: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
const handSuitLabelMap: Record<Tile['suit'], HandSuitLabel> = {
|
||||||
|
W: '万',
|
||||||
|
T: '筒',
|
||||||
|
B: '条',
|
||||||
|
}
|
||||||
|
|
||||||
|
const visibleHandTileGroups = computed(() => {
|
||||||
|
const grouped = new Map<HandSuitLabel, Tile[]>()
|
||||||
|
|
||||||
|
myHandTiles.value
|
||||||
|
.slice()
|
||||||
|
.sort((left, right) => {
|
||||||
|
const suitDiff = handSuitOrder[left.suit] - handSuitOrder[right.suit]
|
||||||
|
if (suitDiff !== 0) {
|
||||||
|
return suitDiff
|
||||||
|
}
|
||||||
|
|
||||||
|
const valueDiff = left.value - right.value
|
||||||
|
if (valueDiff !== 0) {
|
||||||
|
return valueDiff
|
||||||
|
}
|
||||||
|
|
||||||
|
return left.id - right.id
|
||||||
|
})
|
||||||
|
.forEach((tile) => {
|
||||||
|
const label = handSuitLabelMap[tile.suit]
|
||||||
|
const current = grouped.get(label) ?? []
|
||||||
|
current.push(tile)
|
||||||
|
grouped.set(label, current)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (['万', '筒', '条'] as HandSuitLabel[])
|
||||||
|
.map((suit) => ({
|
||||||
|
suit,
|
||||||
|
tiles: grouped.get(suit) ?? [],
|
||||||
|
}))
|
||||||
|
.filter((group) => group.tiles.length > 0)
|
||||||
|
})
|
||||||
|
|
||||||
const visibleHandTiles = computed(() => {
|
const visibleHandTiles = computed(() => {
|
||||||
if (gameStore.phase === 'waiting') {
|
if (gameStore.phase === 'waiting') {
|
||||||
return []
|
return []
|
||||||
@@ -1517,9 +1563,14 @@ onBeforeUnmount(() => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="player-hand" v-if="visibleHandTiles.length > 0">
|
<div class="player-hand" v-if="visibleHandTiles.length > 0">
|
||||||
|
<div
|
||||||
|
v-for="group in visibleHandTileGroups"
|
||||||
|
:key="group.suit"
|
||||||
|
class="player-hand-group"
|
||||||
|
:data-suit="group.suit"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
v-for="tile in visibleHandTiles"
|
v-for="tile in group.tiles"
|
||||||
:key="tile.id"
|
:key="tile.id"
|
||||||
class="tile-chip"
|
class="tile-chip"
|
||||||
:class="{ selected: selectedTile === formatTile(tile) }"
|
:class="{ selected: selectedTile === formatTile(tile) }"
|
||||||
@@ -1535,6 +1586,7 @@ onBeforeUnmount(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<aside class="ws-sidebar">
|
<aside class="ws-sidebar">
|
||||||
|
|||||||
Reference in New Issue
Block a user