959 lines
27 KiB
Vue
959 lines
27 KiB
Vue
<template>
|
|
<view class="page-container">
|
|
<!-- Top Header Area -->
|
|
<view class="top-header">
|
|
<image
|
|
class="header-bg"
|
|
src="/static/images/login_bg.png"
|
|
mode="aspectFill"
|
|
></image>
|
|
<view class="header-overlay"></view>
|
|
<view class="status-bar"></view>
|
|
<view class="header-content">
|
|
<!-- User Info Row -->
|
|
<view class="user-bar">
|
|
<view class="brand-side">
|
|
<view class="brand-logo-shell">
|
|
<image
|
|
class="brand-logo"
|
|
src="/static/logo.png"
|
|
mode="aspectFit"
|
|
></image>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="header-right">
|
|
<view class="user-summary" @click="goPage('/pages/user/index')">
|
|
<text class="username">{{ userInfo.username || $lang.guest }}</text>
|
|
<view class="balance-pill">
|
|
<text class="currency-symbol">₫</text>
|
|
<text class="balance-text">{{
|
|
$fk(userInfo.money) || "0.00"
|
|
}}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="right-actions">
|
|
<view class="action-btn" @click="goService">
|
|
<u-icon name="server-fill" color="#f6e7bf" size="20"></u-icon>
|
|
</view>
|
|
<view class="action-btn" @click="goPage('/pages/user/index')">
|
|
<u-icon name="grid-fill" color="#f6e7bf" size="20"></u-icon>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- Banner Area -->
|
|
<view class="banner-area">
|
|
<u-swiper
|
|
:list="bannerList"
|
|
height="150"
|
|
radius="14"
|
|
indicator
|
|
indicatorMode="line"
|
|
circular
|
|
></u-swiper>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- Main Content Layout -->
|
|
<view class="main-body">
|
|
<!-- Left Sidebar -->
|
|
<scroll-view scroll-y class="sidebar">
|
|
<view
|
|
class="sidebar-item"
|
|
v-for="(cat, index) in categories"
|
|
:key="index"
|
|
:class="{ active: currentCategory === cat.id }"
|
|
@click="switchCategory(cat.id)"
|
|
>
|
|
<view class="item-marker"></view>
|
|
<view class="icon-box">
|
|
<image :src="cat.icon" mode="widthFix" style="width: 22px; height: 22px;" v-if="cat.icon" />
|
|
<u-icon
|
|
:name="cat.uIcon"
|
|
:color="currentCategory === cat.id ? '#f1d392' : '#d1c6aa'"
|
|
size="24"
|
|
v-else
|
|
></u-icon>
|
|
</view>
|
|
<view class="cat-texts">
|
|
<text class="cat-name">{{ $lang[cat.nameKey] }}</text>
|
|
<text class="cat-count">{{ getCategoryCount(cat.id) }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- Online Count Bottom -->
|
|
<view class="online-count-box">
|
|
<text class="label">{{ $lang.onlineCount }}</text>
|
|
<text class="count">{{ onlineNum }}</text>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<!-- Right Content Area -->
|
|
<scroll-view scroll-y class="content-area">
|
|
<view class="table-list">
|
|
<view class="loading-state" v-if="loading">
|
|
<u-loading-icon color="#f4c46f" vertical :text="$lang.loading"></u-loading-icon>
|
|
</view>
|
|
|
|
<view
|
|
class="game-card"
|
|
v-for="(item, index) in filteredTables"
|
|
:key="index"
|
|
@click="enterGame(item)"
|
|
>
|
|
<!-- Card Header -->
|
|
<view class="card-header">
|
|
<view class="header-left">
|
|
<text class="table-name">{{ item.table_name }}</text>
|
|
</view>
|
|
<view class="header-right">
|
|
<text class="limit-info">{{ $lang.maxLimit }}:{{ $fk((item.game_id == 4 || item.game_id == 5) && userInfo.limit_high_nn > 0 ? userInfo.limit_high_nn : (userInfo.limit_high || 0)) }} {{ $lang.minLimit }}:{{ (item.game_id == 4 || item.game_id == 5) && userInfo.limit_low_nn > 0 ? userInfo.limit_low_nn : (userInfo.limit_low || 0) }}</text>
|
|
<view class="status-live">
|
|
<view class="status-dot" :class="{ 'is-live': item.status===1 }"></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- Roadmap Visualization (Body) -->
|
|
<view class="card-body">
|
|
<view class="card-body-overlay"></view>
|
|
<!-- 百家乐/龙虎: 珠盘路圆圈 -->
|
|
<view class="roadmap-grid" v-if="item.game_id !== 4 && item.game_id !== 5">
|
|
<view
|
|
v-for="(cell, cIdx) in item.beadRoad"
|
|
:key="cIdx"
|
|
class="road-cell"
|
|
:style="{
|
|
left: ((cell.show_x - 1) * cellWidth) + 'px',
|
|
top: ((cell.show_y - 1) * cellHeight) + 'px'
|
|
}"
|
|
:class="getCellClass(cell.result)"
|
|
>
|
|
<text class="cell-text">{{ getResultText(cell.result, item.game_id) }}</text>
|
|
</view>
|
|
</view>
|
|
<!-- 牛牛/三卡: 表格路单 -->
|
|
<view class="nn-roadmap" v-else>
|
|
<view class="nn-row" v-for="row in 4" :key="row">
|
|
<view class="nn-label" :class="row === 1 ? 'nn-label-banker' : 'nn-label-player'">
|
|
{{ ['', '庄', '闲1', '闲2', '闲3'][row] }}
|
|
</view>
|
|
<scroll-view scroll-x class="nn-cells">
|
|
<view class="nn-cells-inner">
|
|
<view
|
|
v-for="(cell, cIdx) in getNNRowData(item.beadRoad, row)"
|
|
:key="cIdx"
|
|
class="nn-cell"
|
|
:class="{ 'nn-win': cell.is_win == 1, 'nn-win-banker': cell.is_win == 1 && row === 1 }"
|
|
>
|
|
<text class="nn-text" :class="cell.type == 1 ? 'nn-text-red' : 'nn-text-blue'">{{ getNNResultText(cell.result) }}</text>
|
|
<text class="nn-win-tag" v-if="cell.is_win == 1">WIN</text>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- Center Overlay Status -->
|
|
<view class="center-overlay" v-if="true">
|
|
<view class="status-badge-lg" :class="getStatusClass(item.bet_status)">
|
|
<u-icon name="hourglass" size="20" color="#fff" v-if="item.bet_status == 1"></u-icon>
|
|
<u-icon name="lock" size="20" color="#fff" v-else-if="item.bet_status == 2"></u-icon>
|
|
<u-icon name="play-circle" size="20" color="#fff" v-else></u-icon>
|
|
|
|
<text class="status-text-lg">
|
|
{{ getStatusText(item.bet_status) }}
|
|
</text>
|
|
<text class="countdown-text" v-if="item.countdown > 0">{{ item.countdown }}s</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view style="height: 60px;"></view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapState } from "vuex";
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
userInfo: {},
|
|
bannerList: [
|
|
'/static/images/new_banner_1.jpg',
|
|
'/static/images/new_banner_2.jpg',
|
|
],
|
|
currentCategory: 0, // 0 = All or default category
|
|
categories: [
|
|
// Mapping based on common IDs: 1=Baccarat, 2=DT, 4=Bull, 5=ThreeCard
|
|
{ id: 1, nameKey: 'baccarat', uIcon: 'chrome-circle-fill', gameIds: [1] },
|
|
{ id: 2, nameKey: 'longhu', uIcon: 'heart-fill', gameIds: [2] },
|
|
{ id: 4, nameKey: 'niuniu', uIcon: 'thumb-up-fill', gameIds: [4] },
|
|
],
|
|
allTables: [],
|
|
loading: false,
|
|
timer: null,
|
|
onlineNum: 0,
|
|
|
|
// Roadmap config
|
|
cellWidth: 16.5, // slightly adjusted for mobile fit
|
|
cellHeight: 17,
|
|
};
|
|
},
|
|
computed: {
|
|
...mapState({
|
|
storeUserInfo: (state) => state.app.userInfo,
|
|
language: (state) => state.app.language,
|
|
$lang: (state) => state.app.lang[state.app.language],
|
|
}),
|
|
filteredTables() {
|
|
if (!this.allTables.length) return [];
|
|
const currentCatParams = this.categories.find(c => c.id === this.currentCategory);
|
|
if (!currentCatParams) return this.allTables;
|
|
|
|
return this.allTables.filter(t => currentCatParams.gameIds.includes(t.game_id));
|
|
}
|
|
},
|
|
onShow() {
|
|
// Sync userInfo
|
|
this.userInfo = this.storeUserInfo || {};
|
|
this.startPolling();
|
|
},
|
|
onHide() {
|
|
this.stopPolling();
|
|
},
|
|
methods: {
|
|
goPage(url) {
|
|
uni.navigateTo({ url });
|
|
},
|
|
goService() {
|
|
// 跳转到客服页面
|
|
uni.navigateTo({
|
|
url: '/pages/user/customservice'
|
|
});
|
|
},
|
|
switchCategory(id) {
|
|
this.currentCategory = id;
|
|
},
|
|
getCategoryCount(id) {
|
|
if (!this.allTables) return 0;
|
|
const cat = this.categories.find(c => c.id === id);
|
|
if (!cat) return 0;
|
|
return this.allTables.filter(t => cat.gameIds.includes(t.game_id)).length;
|
|
},
|
|
startPolling() {
|
|
this.loadData();
|
|
this.timer = setInterval(() => {
|
|
this.loadData();
|
|
}, 3000);
|
|
},
|
|
stopPolling() {
|
|
if(this.timer) clearInterval(this.timer);
|
|
},
|
|
async loadData() {
|
|
if(!this.userInfo.id) return;
|
|
try {
|
|
const res = await this.$api.getAllTable({
|
|
user_id: this.userInfo.id,
|
|
api_token: this.userInfo.api_token
|
|
});
|
|
if (res.Success && res.Data) {
|
|
this.processData(res.Data);
|
|
this.updateOnlineNum();
|
|
}
|
|
} catch(e) {
|
|
console.error(e);
|
|
}
|
|
},
|
|
updateOnlineNum() {
|
|
const hour = new Date().getHours();
|
|
const base = 800;
|
|
const extra = (hour >= 0 && hour < 6) ? 200 : 0;
|
|
this.onlineNum = base + extra + Math.floor(Math.random() * 100);
|
|
},
|
|
processData(data) {
|
|
// Transform data for UI
|
|
this.allTables = data.map(item => {
|
|
// Extract Bead Road (showRoad usually)
|
|
// Note: In helper.php, waybill() returns { showRoad, bigRoad ... }
|
|
let beadRoad = [];
|
|
if (item.game_id == 4 || item.game_id == 5) {
|
|
// 牛牛/三卡: ludan.waybill 直接就是数组,只取最后7列
|
|
if (item.ludan && Array.isArray(item.ludan.waybill)) {
|
|
let all = item.ludan.waybill;
|
|
let maxX = Math.max(...all.map(c => c.show_x), 0);
|
|
let keepCols = 7;
|
|
let cutX = Math.max(maxX - keepCols, 0);
|
|
beadRoad = all.filter(c => c.show_x > cutX).map(c => ({...c, show_x: c.show_x - cutX}));
|
|
}
|
|
} else if (item.ludan && item.ludan.waybill && item.ludan.waybill.showRoad) {
|
|
beadRoad = item.ludan.waybill.showRoad;
|
|
}
|
|
|
|
// Adjust roadmap to keep latest on screen (simple truncation logic for demo)
|
|
// Real logic might need scrolling or windowing
|
|
// For card display, we usually show last X columns
|
|
|
|
return {
|
|
...item,
|
|
beadRoad: beadRoad,
|
|
// Mock countdown if not provided
|
|
countdown: item.countdown || 15
|
|
};
|
|
});
|
|
},
|
|
// Visual Helpers
|
|
getCellClass(result) {
|
|
// 1=Banker(Red), 2=Player(Blue), 3=Tie(Green)
|
|
if (result === 1) return 'cell-red';
|
|
if (result === 2) return 'cell-blue';
|
|
if (result === 3) return 'cell-green';
|
|
return '';
|
|
},
|
|
getResultText(result, gameId) {
|
|
if (gameId == 2) {
|
|
if (result === 1) return '龙';
|
|
if (result === 2) return '虎';
|
|
if (result === 3) return '和';
|
|
}
|
|
if (result === 1) return '庄';
|
|
if (result === 2) return '闲';
|
|
if (result === 3) return '和';
|
|
return '';
|
|
},
|
|
getNNRowData(beadRoad, row) {
|
|
return beadRoad.filter(cell => cell.show_y === row);
|
|
},
|
|
getNNResultText(result) {
|
|
if (result == 0) return '无牛';
|
|
if (result >= 1 && result <= 9) return '牛' + result;
|
|
if (result == 10) return '牛牛';
|
|
if (result == 11) return '五公';
|
|
if (result == 12) return '豹子';
|
|
if (result == 13) return '同花顺';
|
|
return '牛' + result;
|
|
},
|
|
getStatusClass(status) {
|
|
// 1: betting, 2: dealing/disabled
|
|
if (status === 1) return 'status-betting';
|
|
return 'status-dealing';
|
|
},
|
|
getStatusText(status) {
|
|
if (status === 1) return this.$lang.betting;
|
|
if (status === 2) return this.$lang.dealing;
|
|
return this.$lang.preparing;
|
|
},
|
|
enterGame(item) {
|
|
// 跳转到同域名下的 /game 子目录
|
|
const portalUrl = window.location.origin + '/#/pages/index';
|
|
const url = `/game/?token=${this.userInfo.api_token}&language=${this.language}&from=portal&returnUrl=${encodeURIComponent(portalUrl)}#/play?id=${item.id}`;
|
|
window.location.href = url;
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
/* Global Layout */
|
|
.page-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100vh;
|
|
background: linear-gradient(180deg, #060505 0%, #0d0b09 100%);
|
|
color: #fff6e1;
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
}
|
|
|
|
/* Header */
|
|
.top-header {
|
|
flex-shrink: 0;
|
|
position: relative;
|
|
padding-bottom: 14px;
|
|
overflow: hidden;
|
|
|
|
.header-bg {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: 0;
|
|
opacity: 0.42;
|
|
}
|
|
|
|
.header-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 0;
|
|
background: linear-gradient(
|
|
180deg,
|
|
rgba(5, 4, 4, 0.86) 0%,
|
|
rgba(11, 9, 8, 0.66) 54%,
|
|
rgba(13, 11, 9, 0.96) 100%
|
|
);
|
|
}
|
|
|
|
.status-bar {
|
|
height: var(--status-bar-height);
|
|
width: 100%;
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.header-content {
|
|
position: relative;
|
|
z-index: 1;
|
|
padding: 8px 12px 0;
|
|
}
|
|
|
|
.user-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
padding: 6px 4px 14px;
|
|
|
|
.brand-side {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.brand-logo-shell {
|
|
width: 58px;
|
|
height: 58px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.brand-logo {
|
|
width: 44px;
|
|
height: 44px;
|
|
display: block;
|
|
}
|
|
|
|
.header-right {
|
|
min-width: 0;
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
}
|
|
|
|
.user-summary {
|
|
min-width: 0;
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 7px;
|
|
}
|
|
|
|
.username {
|
|
max-width: 100%;
|
|
font-size: 16px;
|
|
font-weight: 700;
|
|
color: #fbf3e0;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.balance-pill {
|
|
width: fit-content;
|
|
max-width: 100%;
|
|
min-height: 30px;
|
|
padding: 0 12px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
border-radius: 999px;
|
|
background: rgba(10, 9, 8, 0.72);
|
|
border: 1px solid rgba(223, 189, 120, 0.24);
|
|
box-shadow: inset 0 1px 0 rgba(255, 243, 219, 0.04);
|
|
|
|
.currency-symbol {
|
|
color: #f1cc84;
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
}
|
|
.balance-text {
|
|
color: #f6e1b2;
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
}
|
|
}
|
|
|
|
.right-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
flex-shrink: 0;
|
|
|
|
.action-btn {
|
|
width: 42px;
|
|
height: 42px;
|
|
border-radius: 15px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: rgba(12, 11, 10, 0.72);
|
|
border: 1px solid rgba(223, 189, 120, 0.16);
|
|
box-shadow: inset 0 1px 0 rgba(255, 244, 220, 0.04);
|
|
}
|
|
}
|
|
}
|
|
|
|
.banner-area {
|
|
position: relative;
|
|
z-index: 1;
|
|
padding: 0 2px;
|
|
|
|
::v-deep .u-swiper {
|
|
border-radius: 18px !important;
|
|
overflow: hidden;
|
|
border: 1px solid rgba(223, 189, 120, 0.14);
|
|
box-shadow: 0 16px 34px rgba(0, 0, 0, 0.24);
|
|
}
|
|
|
|
::v-deep .u-swiper__wrapper__item__wrapper {
|
|
border-radius: 18px !important;
|
|
}
|
|
|
|
::v-deep .u-swiper-indicator {
|
|
bottom: 10px !important;
|
|
}
|
|
|
|
::v-deep .u-swiper-indicator__wrapper__item {
|
|
background-color: rgba(255, 244, 220, 0.28) !important;
|
|
}
|
|
|
|
::v-deep .u-swiper-indicator__wrapper__item--active {
|
|
background-color: #dfbd78 !important;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Body Layout */
|
|
.main-body {
|
|
flex: 1;
|
|
display: flex;
|
|
overflow: hidden;
|
|
gap: 10px;
|
|
padding: 0 12px 12px;
|
|
|
|
/* Sidebar styles */
|
|
.sidebar {
|
|
width: 86px;
|
|
background: linear-gradient(
|
|
180deg,
|
|
rgba(18, 15, 13, 0.98) 0%,
|
|
rgba(10, 9, 8, 0.98) 100%
|
|
);
|
|
border: 1px solid rgba(223, 189, 120, 0.14);
|
|
border-radius: 22px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.18);
|
|
|
|
.sidebar-item {
|
|
position: relative;
|
|
margin: 6px;
|
|
padding: 14px 6px 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 18px;
|
|
transition: all 0.25s ease;
|
|
|
|
.item-marker {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 0;
|
|
width: 20px;
|
|
height: 3px;
|
|
border-radius: 999px;
|
|
transform: translateX(-50%);
|
|
background: transparent;
|
|
}
|
|
|
|
&.active {
|
|
background: linear-gradient(
|
|
180deg,
|
|
rgba(59, 43, 19, 0.24) 0%,
|
|
rgba(27, 20, 12, 0.08) 100%
|
|
);
|
|
box-shadow: inset 0 1px 0 rgba(255, 239, 203, 0.06);
|
|
|
|
.item-marker {
|
|
background: linear-gradient(90deg, #f2ddb3 0%, #dbaf57 100%);
|
|
}
|
|
|
|
.icon-box {
|
|
background: rgba(223, 189, 120, 0.08);
|
|
border-color: rgba(223, 189, 120, 0.18);
|
|
}
|
|
|
|
.cat-name,
|
|
.cat-count {
|
|
color: #f1d392;
|
|
}
|
|
}
|
|
|
|
.icon-box {
|
|
width: 40px;
|
|
height: 40px;
|
|
margin-bottom: 8px;
|
|
border-radius: 14px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: rgba(14, 13, 12, 0.8);
|
|
border: 1px solid rgba(255, 255, 255, 0.03);
|
|
}
|
|
|
|
.cat-texts {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 5px;
|
|
}
|
|
|
|
.cat-name {
|
|
font-size: 11px;
|
|
color: #cdc2a3;
|
|
text-align: center;
|
|
word-break: break-word;
|
|
line-height: 1.25;
|
|
max-width: 70px;
|
|
}
|
|
.cat-count {
|
|
min-width: 32px;
|
|
height: 22px;
|
|
padding: 0 9px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
line-height: 1;
|
|
color: #e3c27a;
|
|
font-variant-numeric: tabular-nums;
|
|
letter-spacing: 0.2px;
|
|
background: linear-gradient(
|
|
180deg,
|
|
rgba(29, 24, 19, 0.96) 0%,
|
|
rgba(16, 13, 11, 0.96) 100%
|
|
);
|
|
border: 1px solid rgba(223, 189, 120, 0.12);
|
|
box-shadow: inset 0 1px 0 rgba(255, 245, 223, 0.04);
|
|
border-radius: 999px;
|
|
}
|
|
}
|
|
|
|
.online-count-box {
|
|
margin: auto 6px 6px;
|
|
padding: 14px 6px calc(14px + env(safe-area-inset-bottom));
|
|
border-top: 1px solid rgba(223, 189, 120, 0.1);
|
|
text-align: center;
|
|
|
|
.label {
|
|
font-size: 10px;
|
|
color: #8d7a55;
|
|
display: block;
|
|
margin-bottom: 4px;
|
|
}
|
|
.count {
|
|
margin-top: 6px;
|
|
font-size: 15px;
|
|
color: #f1cc84;
|
|
font-weight: 700;
|
|
font-variant-numeric: tabular-nums;
|
|
letter-spacing: 0.3px;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Content styles */
|
|
.content-area {
|
|
flex: 1;
|
|
background: rgba(8, 7, 6, 0.52);
|
|
border: 1px solid rgba(223, 189, 120, 0.1);
|
|
border-radius: 22px;
|
|
padding: 12px;
|
|
box-shadow: inset 0 1px 0 rgba(255, 244, 220, 0.03);
|
|
|
|
.table-list {
|
|
min-height: 100%;
|
|
}
|
|
|
|
.loading-state {
|
|
min-height: 180px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.game-card {
|
|
margin-bottom: 14px;
|
|
background: linear-gradient(
|
|
180deg,
|
|
rgba(21, 18, 15, 0.98) 0%,
|
|
rgba(14, 12, 10, 0.98) 100%
|
|
);
|
|
border: 1px solid rgba(223, 189, 120, 0.14);
|
|
border-radius: 18px;
|
|
overflow: hidden;
|
|
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.16);
|
|
|
|
.card-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 10px 12px;
|
|
min-height: 44px;
|
|
background: linear-gradient(
|
|
180deg,
|
|
rgba(30, 25, 20, 0.88) 0%,
|
|
rgba(19, 17, 14, 0.88) 100%
|
|
);
|
|
border-bottom: 1px solid rgba(223, 189, 120, 0.1);
|
|
|
|
.table-name {
|
|
font-size: 14px;
|
|
color: #f9f1de;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.header-right {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.limit-info {
|
|
font-size: 10px;
|
|
color: #bca987;
|
|
text-align: right;
|
|
line-height: 1.35;
|
|
}
|
|
|
|
.status-live {
|
|
width: 18px;
|
|
height: 18px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 999px;
|
|
background: rgba(255, 255, 255, 0.03);
|
|
}
|
|
|
|
.status-dot {
|
|
width: 7px;
|
|
height: 7px;
|
|
border-radius: 50%;
|
|
background-color: #6f6658;
|
|
|
|
&.is-live {
|
|
background-color: #53c57b;
|
|
box-shadow: 0 0 10px rgba(83, 197, 123, 0.28);
|
|
}
|
|
}
|
|
}
|
|
|
|
.card-body {
|
|
position: relative;
|
|
height: 114px;
|
|
background: linear-gradient(180deg, #fbf9f3 0%, #f0ece3 100%);
|
|
}
|
|
|
|
.card-body-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
background: linear-gradient(
|
|
180deg,
|
|
rgba(255, 255, 255, 0.02) 0%,
|
|
rgba(0, 0, 0, 0.02) 100%
|
|
);
|
|
}
|
|
|
|
.roadmap-grid {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: relative;
|
|
background-size: 16.5px 17px;
|
|
background-image: linear-gradient(to right, #dad3c7 1px, transparent 1px),
|
|
linear-gradient(to bottom, #dad3c7 1px, transparent 1px);
|
|
|
|
.road-cell {
|
|
position: absolute;
|
|
width: 14px;
|
|
height: 14px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border: 1px solid rgba(0, 0, 0, 0.08);
|
|
background-color: #fff;
|
|
|
|
&.cell-red {
|
|
border: 2px solid #cf4444;
|
|
color: #cf4444;
|
|
}
|
|
&.cell-blue {
|
|
border: 2px solid #467ed7;
|
|
color: #467ed7;
|
|
}
|
|
&.cell-green {
|
|
border: 2px solid #4ba96f;
|
|
color: #4ba96f;
|
|
}
|
|
|
|
.cell-text {
|
|
font-size: 9px;
|
|
font-weight: 700;
|
|
}
|
|
}
|
|
}
|
|
|
|
.nn-roadmap {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: linear-gradient(180deg, #fbf9f3 0%, #f0ece3 100%);
|
|
|
|
.nn-row {
|
|
display: flex;
|
|
flex: 1;
|
|
border-bottom: 1px solid #ddd4c8;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
}
|
|
|
|
.nn-label {
|
|
width: 30px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
color: #fff;
|
|
flex-shrink: 0;
|
|
|
|
&.nn-label-banker {
|
|
background: #a84237;
|
|
}
|
|
&.nn-label-player {
|
|
background: #3c6399;
|
|
}
|
|
}
|
|
|
|
.nn-cells {
|
|
flex: 1;
|
|
}
|
|
|
|
.nn-cells-inner {
|
|
display: flex;
|
|
height: 100%;
|
|
}
|
|
|
|
.nn-cell {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-right: 1px solid #ddd4c8;
|
|
padding: 1px 0;
|
|
}
|
|
|
|
.nn-text {
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
|
|
&.nn-text-red {
|
|
color: #a84237;
|
|
}
|
|
&.nn-text-blue {
|
|
color: #3c6399;
|
|
}
|
|
}
|
|
|
|
.nn-win-tag {
|
|
font-size: 7px;
|
|
color: #fff;
|
|
background: #3c6399;
|
|
padding: 0 3px;
|
|
border-radius: 2px;
|
|
line-height: 1.4;
|
|
margin-top: 1px;
|
|
}
|
|
|
|
.nn-cell.nn-win-banker .nn-win-tag {
|
|
background: #a84237;
|
|
}
|
|
}
|
|
|
|
.center-overlay {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
|
|
.status-badge-lg {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-width: 110px;
|
|
padding: 10px 18px;
|
|
border-radius: 16px;
|
|
color: #fff;
|
|
background: linear-gradient(
|
|
180deg,
|
|
rgba(47, 39, 28, 0.92) 0%,
|
|
rgba(17, 14, 11, 0.92) 100%
|
|
);
|
|
border: 1px solid rgba(223, 189, 120, 0.18);
|
|
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.18);
|
|
|
|
&.status-betting {
|
|
background: linear-gradient(
|
|
180deg,
|
|
rgba(88, 67, 33, 0.92) 0%,
|
|
rgba(24, 18, 11, 0.94) 100%
|
|
);
|
|
}
|
|
|
|
.status-text-lg {
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
margin-top: 4px;
|
|
}
|
|
|
|
.countdown-text {
|
|
font-size: 15px;
|
|
color: #fff5dc;
|
|
margin-top: 2px;
|
|
font-family: monospace;
|
|
font-weight: 700;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style> |