refactor: 重构播放视图UI,提取导航栏,并优化切换标签页和表格列表样式。

This commit is contained in:
li
2026-01-19 16:46:59 +08:00
parent 23b6841d37
commit ff0f34a485
4 changed files with 497 additions and 334 deletions
+309 -202
View File
@@ -7,67 +7,16 @@
]"
>
<!-- Top Navigation Bar -->
<div class="nav">
<div class="left">
<div class="back" @click="handleBack"></div>
<div class="switch-tab" @click.stop="showSwitchtab(true)"></div>
<div class="user">
<div class="name">
{{ userInfo.username }}
</div>
<div class="money">{{ userInfo.money }}</div>
</div>
</div>
<div class="right">
<div
class="cutdown"
v-show="
tableData &&
(tableData.sendMode == 'startBetCountDown' ||
tableData.sendMode == 'toBet' ||
tableData.sendMode == 'toBetFlase')
"
>
<Circle
v-model:current-rate="currentRate"
start-position="left"
:size="38"
:stroke-width="120"
:rate="circle.rate"
:color="{
'0%': '#3fecff',
'100%': '#6149f6'
}"
layer-color="rgba(255,255,255,0.3)"
:text="`${circle.num || 0}`"
/>
</div>
<ul class="box">
<li
class="btn camera"
:class="{ off: !switchVideo }"
@click.stop="showSwitchCamera(true)"
></li>
<li class="btn muise" @click="toggleAplayer"></li>
<li class="btn menu" @click="showMenu"></li>
</ul>
</div>
</div>
<!-- Main View Container: Vertical Flex Stack -->
<div class="view">
<!-- 1. Video & Game Area (Top Section, Flex Grow to fill space) -->
<div class="video-container" ref="videoDom" @click.stop="closeSwitchView(false)">
<!-- Video Iframe -->
<iframe
v-if="switchVideo && tableData"
:style="{
width: foxVideo.w,
height: foxVideo.h,
marginTop: foxVideo.mt,
marginLeft: foxVideo.ml
}"
class="iframe"
:class="[
{
@@ -81,68 +30,7 @@
:src="videoUrl"
></iframe>
<!-- Game Betting Overlay -->
<div class="game-area">
<template
v-if="tableData && (tableData.game_id == 7 || tableData.game_id == 8)"
>
<Transition
name="custom-classes"
enter-active-class="animate__animated animate__faster animate__fadeInRight"
leave-active-class="animate__animated animate__faster animate__fadeOutRight"
>
<PlayTable
v-if="hideVideo"
class="dice-table"
ref="chipTable"
:game_id="tableData?.game_id"
:sendMode="tableData?.sendMode"
:table_id="tableData?.id"
:number_tab_id="tableData?.number_tab_id"
:is_scavenging="tableData?.is_scavenging"
:winArray="winArray"
:bet_amount_msg="tableData?.bet_amount_msg"
:can_bet_big_small="tableData?.can_bet_big_small"
:can_bet_luck_six="tableData?.can_bet_luck_six"
:limit_money="tableData?.limit_money"
:limit_money_pair="tableData?.limit_money_pair"
:limit_money_tie="tableData?.limit_money_tie"
:tableData="tableData"
></PlayTable>
</Transition>
</template>
<template v-else>
<PlayTable
ref="chipTable"
:game_id="tableData?.game_id"
:sendMode="tableData?.sendMode"
:table_id="tableData?.id"
:number_tab_id="tableData?.number_tab_id"
:is_scavenging="tableData?.is_scavenging"
:winArray="winArray"
:bet_amount_msg="tableData?.bet_amount_msg"
:can_bet_big_small="tableData?.can_bet_big_small"
:can_bet_luck_six="tableData?.can_bet_luck_six"
:limit_money="tableData?.limit_money"
:limit_money_pair="tableData?.limit_money_pair"
:limit_money_tie="tableData?.limit_money_tie"
:tableData="tableData"
:class="[
{
hideTable:
tableData &&
(tableData.sendMode == 'sendScanResult' ||
tableData.sendMode == 'endBet') &&
(tableData.game_id == 4 || tableData.game_id == 5)
}
]"
></PlayTable>
</template>
<RushVillage
v-if="tableData && tableData.is_rob == 1"
:thisData="tableData"
></RushVillage>
</div>
<!-- Overlays inside Top Section -->
<div class="switchView animate__fadeIn animated0" v-if="switchtabshow">
@@ -160,6 +48,127 @@
>
<setCamera @showSwitchCamera="showSwitchCamera"></setCamera>
</div>
<!-- Video Overlay Controls (Moved to bottom for stacking context) -->
<div class="video-overlay-controls">
<div class="back" @click="handleBack"></div>
<SwitchTableButton @click="showSwitchtab(true)" />
</div>
<!-- Status/Countdown Overlay (Moved to absolute end for visibility) -->
<div class="status-overlay" v-if="tableData">
<!-- Dealing Status -->
<div class="status-circle dealing" v-if="['endBet', 'sendScanResult', 'openingBaccaratResult', 'openingDtResult', 'openingNnResult', 'openingTcResult', 'openingToningResult', 'openingDiceResult', 'openingRouletteResult'].includes(tableData.sendMode)">
<span>发牌中</span>
</div>
<!-- Countdown -->
<div class="status-circle countdown" v-else-if="tableData.sendMode === 'startBetCountDown' || tableData.sendMode === 'toBet'">
<span>{{ circle.num }}</span>
</div>
<!-- Wait/Shuffle/Other -->
<div class="status-circle wait" v-else-if="!tableData.sendMode || tableData.sendMode === 'changeBoot'">
<span style="font-size: 12px;">洗牌中</span>
</div>
</div>
<!-- Back Button (Top Left) -->
<div class="video-btn-back" @click="handleBack"></div>
</div>
<!-- Top Navigation Bar (Moved below video) -->
<div class="nav">
<!-- 1. User Info -->
<div class="nav-item user-info">
<div class="icon user-icon"></div>
<div class="text">{{ userInfo.username }}</div>
</div>
<!-- 2. Balance -->
<div class="nav-item balance-info">
<div class="icon money-icon"></div>
<div class="text">{{ userInfo.money }}</div>
</div>
<!-- 3. Table Limit -->
<div class="nav-item limit-info">
<div class="icon limit-icon"></div>
<div class="text">{{ tableData && tableData.limit_money }}</div>
</div>
<!-- 4. Right Controls (Camera, etc.) -->
<div class="nav-item right-controls">
<!-- Camera moved to video overlay -->
<div class="btn muise" @click="toggleAplayer"></div>
<div class="btn menu" @click="showMenu"></div>
</div>
</div>
<!-- Game Betting Area (Moved below Nav) -->
<div class="game-area-block">
<div class="game-area-content">
<template
v-if="tableData && (tableData.game_id == 7 || tableData.game_id == 8)"
>
<Transition
name="custom-classes"
enter-active-class="animate__animated animate__faster animate__fadeInRight"
leave-active-class="animate__animated animate__faster animate__fadeOutRight"
>
<PlayTable
v-if="hideVideo"
class="dice-table"
ref="chipTable"
:game_id="tableData?.game_id"
:sendMode="tableData?.sendMode"
:table_id="tableData?.id"
:number_tab_id="tableData?.number_tab_id"
:is_scavenging="tableData?.is_scavenging"
:winArray="winArray"
:bet_amount_msg="tableData?.bet_amount_msg"
:can_bet_big_small="tableData?.can_bet_big_small"
:can_bet_luck_six="tableData?.can_bet_luck_six"
:limit_money="tableData?.limit_money"
:limit_money_pair="tableData?.limit_money_pair"
:limit_money_tie="tableData?.limit_money_tie"
:tableData="tableData"
></PlayTable>
</Transition>
</template>
<template v-else>
<PlayTable
ref="chipTable"
:game_id="tableData?.game_id"
:sendMode="tableData?.sendMode"
:table_id="tableData?.id"
:number_tab_id="tableData?.number_tab_id"
:is_scavenging="tableData?.is_scavenging"
:winArray="winArray"
:bet_amount_msg="tableData?.bet_amount_msg"
:can_bet_big_small="tableData?.can_bet_big_small"
:can_bet_luck_six="tableData?.can_bet_luck_six"
:limit_money="tableData?.limit_money"
:limit_money_pair="tableData?.limit_money_pair"
:limit_money_tie="tableData?.limit_money_tie"
:tableData="tableData"
:class="[
{
hideTable:
tableData &&
(tableData.sendMode == 'sendScanResult' ||
tableData.sendMode == 'endBet') &&
(tableData.game_id == 4 || tableData.game_id == 5)
}
]"
></PlayTable>
</template>
<RushVillage
v-if="tableData && tableData.is_rob == 1"
:thisData="tableData"
></RushVillage>
</div>
</div>
<!-- 2. Chip Control Bar (Middle Section, Fixed Height) -->
@@ -203,7 +212,7 @@
import { ref, computed, watch, nextTick, onUnmounted } from "vue"
import { useRouter, useRoute } from "vue-router"
import { useStore } from "vuex"
import { Circle, showToast, showDialog, closeDialog, closeToast } from "vant"
import { showToast, showDialog, closeDialog, closeToast } from "vant"
import PlayTable from "@/components/PlayTable/Index.vue"
import PlayWay from "@/components/PlayWay.vue"
import PlayChip from "@/components/PlayChip.vue"
@@ -213,6 +222,7 @@ import ToningResult from "@/components/ToningResult"
import DiceResult from "@/components/DiceResult"
import RouletteResult from "@/components/RouletteResult"
import SwitchTab from "@/components/SwitchTab2"
import SwitchTableButton from "@/components/SwitchTableButton"
import setCamera from "@/components/setCamera"
import PlayTypePop from "@/components/PlayTypePop"
import TableInfoPop from "@/components/TableInfoPop"
@@ -234,9 +244,9 @@ export default {
PlayTable,
PlayWay,
PlayChip,
Circle,
Poker,
SwitchTab,
SwitchTableButton,
setCamera,
PlayTypePop,
TableInfoPop,
@@ -1231,95 +1241,80 @@ $gold: #c5a059;
box-sizing: border-box;
overflow: hidden;
/* Navigation Bar */
/* Navigation Bar - Redesigned */
.nav {
position: relative;
z-index: 100;
width: 100%;
height: 45px;
height: 36px; /* Slightly compact */
display: flex;
align-items: center;
justify-content: space-between;
background: $dark-bg-secondary;
border-bottom: 1px solid $border-color;
background: #000; /* Pure black as per ref */
border-bottom: 1px solid #222;
flex-shrink: 0;
padding: 0 10px;
box-sizing: border-box;
.left {
height: 0.923rem;
display: flex;
align-items: center;
gap: 0.3rem;
.back {
width: 0.923rem;
height: 0.923rem;
background: url("~@/assets/images/icon/back.png") center center no-repeat;
background-size: 60% auto;
margin-left: 0.6rem;
}
.switch-tab {
width: 0.923rem;
height: 0.923rem;
background: url("~@/assets/images/icon/switch_tab.png") center center no-repeat;
background-size: 60% auto;
}
.user {
font-size: 13px;
font-weight: 600;
line-height: 1;
margin-left: 10px;
.name {
color: #fff;
padding-left: 20px;
margin-top: 3px;
background: url("~@/assets/images/icon/user.png") left center no-repeat;
background-size: 14px;
}
.money {
color: $gold;
padding-left: 20px;
margin-top: 3px;
background: url("~@/assets/images/icon/money.png") left center no-repeat;
background-size: 14px;
}
}
}
.right {
margin-right: 0.7rem;
display: flex;
align-items: center;
.cutdown {
position: absolute;
left: 50%;
top: 0.15rem;
margin-left: 2rem;
::v-deep .van-circle__text {
color: #fff;
}
}
.box {
.nav-item {
display: flex;
.btn {
width: 0.923rem;
height: 0.7rem;
padding: 0.2rem 0.1rem;
margin-left: 0.677rem;
background-size: 1.2rem;
background-position: center center;
background-repeat: no-repeat;
&.camera {
background-image: url("~@/assets/images/icon/camera.png");
&.off {
background-image: url("~@/assets/images/icon/camera_off.png");
}
}
&.muise {
background-image: url("~@/assets/images/icon/musie.png");
}
&.menu {
background-image: url("~@/assets/images/icon/meun.png");
}
align-items: center;
height: 100%;
color: #fff;
font-size: 13px;
.icon {
width: 16px;
height: 16px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
margin-right: 6px;
}
&.user-info {
.user-icon { background-image: url("~@/assets/images/icon/user.png"); }
.text { font-weight: bold; }
}
&.balance-info {
.money-icon { background-image: url("~@/assets/images/icon/money.png"); }
.text { color: $gold; font-family: monospace; font-size: 14px; }
}
&.limit-info {
/* Use switch_tab icon as placeholder for limit arrows if specific icon invalid,
or styling css borders for arrows */
.limit-icon {
width: 12px; height: 12px;
background-image: url("~@/assets/images/icon/switch_tab.png"); /* Placeholder */
transform: rotate(90deg); /* Make it look like up/down sort */
opacity: 0.7;
}
.text { color: #aaa; font-size: 12px; }
}
&.right-controls {
display: flex;
gap: 15px;
.btn {
width: 24px;
height: 24px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
&.camera {
background-image: url("~@/assets/images/icon/camera.png");
&.off { background-image: url("~@/assets/images/icon/camera_off.png"); }
}
&.muise { background-image: url("~@/assets/images/icon/musie.png"); }
&.menu { background-image: url("~@/assets/images/icon/meun.png"); }
}
}
}
}
}
@@ -1328,7 +1323,7 @@ $gold: #c5a059;
display: flex;
flex-direction: column;
width: 100%;
height: calc(100% - 45px); /* Subtract nav height */
height: 100%; /* Full height, Nav is now inside */
position: relative;
overflow: hidden;
@@ -1342,14 +1337,13 @@ $gold: #c5a059;
.iframe {
border: none;
/* Remove fixed width/height to allow JS dynamic sizing */
/* width: 100%; */
/* height: 100%; */
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 1;
/* object-fit: cover; Remove object-fit as it might conflict with iframe content */
object-fit: cover; /* This won't affect iframe content but is good for semantics if it were a video tag. */
}
.game-area {
@@ -1379,12 +1373,125 @@ $gold: #c5a059;
border-top-left-radius: 0.3rem;
&.camera { width: 40%; }
}
/* Separated Video Controls */
.video-btn-back {
position: absolute;
top: 10px;
left: 10px;
z-index: 2005; /* Highest priority */
width: 30px;
height: 30px;
background-image: url("~@/assets/images/icon/back.png");
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
/* Overlay Camera Icon */
.video-overlay-camera {
position: absolute;
top: 10px;
right: 60px; /* Switch is at 10px, so this is left of it */
z-index: 2001;
width: 30px;
height: 30px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
background-image: url("~@/assets/images/icon/camera.png");
&.off {
background-image: url("~@/assets/images/icon/camera_off.png");
}
}
/* Status Overlay Styles */
.status-overlay {
position: absolute;
top: 60px; /* Moved down to avoid row overlap, or move Left? Let's move LEFT of Camera */
left: 50%;
transform: translateX(-50%); /* Removed translateZ to avoid potential clipping/context issues */
z-index: 2005; /* Matches highest priority buttons */
display: flex;
pointer-events: none; /* Allow clicks to pass through if needed, though buttons inside might need events. Actually, user might want to see it. It's display only. */
align-items: center;
justify-content: center;
.status-circle {
width: 50px;
height: 50px;
border-radius: 50%;
background: rgba(0,0,0,0.6);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-weight: bold;
font-size: 16px;
border: 2px solid rgba(255, 255, 255, 0.2);
backdrop-filter: blur(4px);
&.dealing {
background: rgba(46, 204, 113, 0.8); /* Green */
border-color: #2ecc71;
font-size: 14px;
}
&.countdown {
background: rgba(231, 76, 60, 0.8); /* Red/Orange for countdown */
border-color: #e74c3c;
font-size: 24px;
}
&.wait {
background: rgba(52, 152, 219, 0.8);
border-color: #3498db;
}
}
}
}
/* 4. Game Table Area (New Flex Item) */
.game-area-block {
width: 100%;
height: 200px; /* Fixed height for table area */
flex-shrink: 0;
position: relative;
background: transparent;
z-index: 10;
overflow: hidden;
/* Content wrapper that mimics old absolute positioning for internal components */
.game-area-content {
width: 100%;
height: 100%;
position: relative;
/* Ensure PlayTable fits inside this block */
::v-deep .playtable {
.view {
bottom: 0 !important; /* Anchor to bottom of this block */
top: auto !important;
height: 100% !important; /* Fill the block */
transform: none !important; /* Reset 3D transform for flat view if needed, or keep if 3D desired within this block */
}
/* Adjust portrait mode specifically if needed */
@media screen and (orientation: portrait) {
.view {
height: 100% !important;
border-radius: 0 !important;
}
}
}
}
}
/* 2. Chip Control Bar (Middle) - Fixed Height */
.bet-chip-bar {
width: 100%;
height: 70px;
height: 60px;
flex-shrink: 0;
position: relative;
z-index: 20;
@@ -1395,7 +1502,7 @@ $gold: #c5a059;
/* 3. Roadmap Container (Bottom) - Auto Height for Aspect Ratio */
.roadmap-container {
width: 100%;
height: 180px;
height: 160px;
flex-shrink: 0;
background: #fff;
position: relative;