Files
pk10/App/Views/Web/home.php
T
li 4a94fe36cf feat: 重构代码架构 + 新增报表/跟单/输赢统计功能
- 拆分 HomeController → TransactionController, ReportWebController, FollowPlanController
- 新增 Service 层: TransactionService, ReportService, FollowPlanService
- pk10.php JS 抽离为 4 个独立文件 (sound/race/bet/poll)
- 前台新增报表查询页面 (/report) + 跟单计划页面 (/follow-plan)
- 后台新增跟单计划管理 + 用户输赢明细统计
- 封盘状态显示倒计时 (x:xx)
- 音效仅在开奖弹窗打开时播放
- 路由按模块分组整理
- autoload 支持 App\Services 命名空间
2026-03-27 18:41:06 +08:00

138 lines
7.2 KiB
PHP

<?php use App\Core\I18n; I18n::init(); $t = function($k,$p=[]){return I18n::t($k,$p);}; ?>
<!DOCTYPE html><html lang="<?=I18n::getLang()?>">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>PK10 - <?=$t('home')?></title>
<link rel="stylesheet" href="/Static/css/app.css">
<style>
.user-card{margin:15px;padding:16px;background:#fff;border-radius:16px;display:flex;align-items:center;gap:12px;box-shadow:0 2px 8px rgba(0,0,0,.08)}
.user-avatar{width:44px;height:44px;border-radius:50%;background:#E8F4FF;display:flex;align-items:center;justify-content:center}
.user-avatar svg{width:24px;height:24px;color:#1E90FF}
.user-info{flex:1}
.user-name{font-size:16px;font-weight:600;color:#333;margin-bottom:4px}
.user-balance{font-size:20px;font-weight:700;color:#333}
.action-buttons{display:flex;gap:8px}
.act-btn{display:flex;flex-direction:column;align-items:center;gap:4px;cursor:pointer;background:none;border:none;padding:0}
.act-btn svg{width:24px;height:24px}
.act-btn span{font-size:12px;color:#666}
.nav-tabs{display:flex;justify-content:space-around;align-items:center;height:50px;background:#fff;border-bottom:1px solid #F0F0F0}
.nav-tab{font-size:15px;color:#666;cursor:pointer;position:relative;padding:12px 0;background:none;border:none}
.nav-tab.active{color:#1E90FF;font-weight:600}
.nav-tab.active::after{content:'';position:absolute;bottom:0;left:0;right:0;height:2px;background:#1E90FF}
.content-area{display:flex;min-height:calc(100vh - 200px)}
.left-menu{width:70px;background:#fff;padding:8px 0;border-right:1px solid #F0F0F0}
.left-menu .mi{height:50px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-size:12px;color:#666;cursor:pointer}
.left-menu .mi.active{color:#1E90FF;background:#F0F8FF}
.left-menu .mi svg{width:20px;height:20px}
.game-area{flex:1;padding:12px;background:#F5F5F5}
.game-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.game-card{height:100px;border-radius:12px;position:relative;display:block;cursor:pointer;overflow:hidden;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,.06);text-decoration:none}
.game-card:active{transform:scale(.98)}
.game-card-inner{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;background:linear-gradient(135deg,#F0F8FF,#E0EFFF);border-radius:12px}
.game-card-inner svg{width:36px;height:36px;color:#1E90FF}
.game-card-inner .gname{font-size:13px;font-weight:600;color:#333}
.game-card.disabled{opacity:.5;pointer-events:none}
.section-title{font-size:16px;font-weight:600;color:#333;margin-bottom:12px;padding:0 0 0 4px}
</style>
</head>
<body style="background:#F5F5F5;padding-bottom:60px">
<!-- 用户卡片 -->
<div class="user-card">
<div class="user-avatar"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></div>
<div class="user-info">
<div class="user-name"><?=htmlspecialchars($user['username']??'')?></div>
<div class="user-balance"><?=number_format($user['balance']??0,2)?></div>
</div>
<div class="action-buttons">
<button class="act-btn" onclick="doDeposit()">
<svg viewBox="0 0 24 24" fill="none" stroke="#1E90FF" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>
<span><?=$t('deposit')?></span>
</button>
<button class="act-btn" onclick="doWithdraw()">
<svg viewBox="0 0 24 24" fill="none" stroke="#1E90FF" stroke-width="2"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg>
<span><?=$t('withdraw')?></span>
</button>
<button class="act-btn" onclick="doTransfer()">
<svg viewBox="0 0 24 24" fill="none" stroke="#1E90FF" stroke-width="2"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg>
<span><?=$t('transfer')?></span>
</button>
</div>
</div>
<!-- 导航标签 -->
<div class="nav-tabs">
<button class="nav-tab active"><?=$t('lottery_tab')?></button>
</div>
<!-- 内容区 -->
<div class="content-area">
<div class="left-menu">
<div class="mi active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polygon points="10 8 16 12 10 16 10 8"/></svg>
<span><?=$t('racing')?></span>
</div>
</div>
<div class="game-area">
<div class="section-title"><?=$t('racing')?></div>
<div class="game-grid">
<?php if($game): ?>
<a href="/game/pk10" class="game-card">
<div class="game-card-inner">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="7" cy="17" r="2"/><circle cx="17" cy="17" r="2"/><path d="M5 17H3v-4l2-5h9l4 5h3v4h-2"/><path d="M5 12h14"/></svg>
<div class="gname"><?=htmlspecialchars($game['name']??$t('pk10_title'))?></div>
</div>
</a>
<?php endif; ?>
<div class="game-card disabled">
<div class="game-card-inner" style="background:linear-gradient(135deg,#F5F5F5,#EBEBEB)">
<svg viewBox="0 0 24 24" fill="none" stroke="#999" stroke-width="2"><rect x="2" y="7" width="20" height="15" rx="2" ry="2"/><polyline points="17 2 12 7 7 2"/></svg>
<div class="gname" style="color:#999"><?=$t('more_games')?></div>
</div>
</div>
</div>
</div>
</div>
<script>
function doDeposit(){
var url='<?=\App\Core\SettingsHelper::get("customer_service_url")?>';
if(!url){alert('<?=$t("contact_admin")?>');return;}
var amount=prompt('<?=$t("deposit_amount")?>');
if(!amount||isNaN(amount)||parseFloat(amount)<=0)return;
fetch('/api/fund-request',{
method:'POST',headers:{'Content-Type':'application/json'},
body:JSON.stringify({type:'deposit',amount:parseFloat(amount)})
}).then(function(r){return r.json();}).then(function(d){
if(d.success){alert('<?=$t("deposit_submitted")?>');window.open(url,'_blank');location.reload();}
else{alert(d.message||'<?=$t("error")?>');}
});
}
function doWithdraw(){
var amount=prompt('<?=$t("withdraw_amount")?>');
if(!amount||isNaN(amount)||parseFloat(amount)<=0)return;
fetch('/api/fund-request',{
method:'POST',headers:{'Content-Type':'application/json'},
body:JSON.stringify({type:'withdraw',amount:parseFloat(amount)})
}).then(function(r){return r.json();}).then(function(d){
if(d.success){alert('<?=$t("withdraw_submitted")?>');location.reload();}
else{alert(d.message||'<?=$t("error")?>');}
});
}
function doTransfer(){
var to=prompt('<?=$t("transfer_to")?>');
if(!to||!to.trim())return;
var amount=prompt('<?=$t("transfer_amount")?>');
if(!amount||isNaN(amount)||parseFloat(amount)<=0)return;
if(!confirm('<?=$t("transfer_confirm")?> '+to+' , <?=$t("amount")?>: '+amount))return;
fetch('/api/transfer',{
method:'POST',headers:{'Content-Type':'application/json'},
body:JSON.stringify({to_username:to.trim(),amount:parseFloat(amount)})
}).then(function(r){return r.json();}).then(function(d){
if(d.success){alert(d.message||'<?=$t("transfer_success")?>');location.reload();}
else{alert(d.message||'<?=$t("error")?>');}
});
}
</script>
<?php $navActive='game'; include __DIR__.'/_nav.php'; ?>
</body></html>