Files
shuiguoji/admin/index.php
T
2026-07-23 08:58:13 +08:00

57 lines
19 KiB
PHP

<?php
declare(strict_types=1);
require dirname(__DIR__) . '/includes/bootstrap.php';
require dirname(__DIR__) . '/includes/game_engine.php';
$admin=require_admin();$view=(string)($_GET['view']??'dashboard');$allowed=['dashboard','users','recharges','withdrawals','cards','referrals','game','settings'];if(!in_array($view,$allowed,true))$view='dashboard';$flash=take_flash();$pdo=db();
$stats=['users'=>(int)$pdo->query('SELECT COUNT(*) FROM users')->fetchColumn(),'pending'=>(int)$pdo->query("SELECT COUNT(*) FROM recharge_orders WHERE status='pending'")->fetchColumn(),'balance'=>(float)$pdo->query('SELECT COALESCE(SUM(balance),0) FROM users')->fetchColumn(),'today'=>(float)$pdo->query("SELECT COALESCE(SUM(amount),0) FROM recharge_orders WHERE status='approved' AND reviewed_at >= '".date('Y-m-d 00:00:00')."'")->fetchColumn()];
$users=$orders=$cards=$withdrawals=$referrals=[];
$generatedCardCodes = [];
if ($view === 'cards' && isset($_SESSION['generated_card_codes']) && is_array($_SESSION['generated_card_codes'])) {
$generatedCardCodes = array_values(array_filter($_SESSION['generated_card_codes'], 'is_string'));
unset($_SESSION['generated_card_codes']);
}
if($view==='users'){$q=trim((string)($_GET['q']??''));if($q!==''){$stmt=$pdo->prepare('SELECT * FROM users WHERE username LIKE ? OR id = ? ORDER BY id DESC LIMIT 100');$stmt->execute(['%'.$q.'%',(int)$q]);$users=$stmt->fetchAll();}else $users=$pdo->query('SELECT * FROM users ORDER BY id DESC LIMIT 100')->fetchAll();}
if(in_array($view,['dashboard','recharges'],true)){$orders=$pdo->query('SELECT r.*,u.username FROM recharge_orders r JOIN users u ON u.id=r.user_id ORDER BY r.id DESC LIMIT 100')->fetchAll();}
if($view==='cards')$cards=$pdo->query('SELECT c.*,u.username,(SELECT COUNT(*) FROM recharge_card_redemptions r WHERE r.card_id=c.id) AS redemption_count FROM recharge_cards c LEFT JOIN users u ON u.id=c.used_by ORDER BY c.id DESC LIMIT 100')->fetchAll();
if($view==='withdrawals')$withdrawals=$pdo->query('SELECT w.*,u.username FROM withdrawal_orders w JOIN users u ON u.id=w.user_id ORDER BY w.id DESC LIMIT 100')->fetchAll();
if($view==='referrals')$referrals=$pdo->query('SELECT r.*,i.username AS inviter_name,e.username AS invitee_name FROM referral_rewards r JOIN users i ON i.id=r.inviter_id JOIN users e ON e.id=r.invitee_id ORDER BY r.id DESC LIMIT 100')->fetchAll();
$referralStats=['rewarded'=>(int)$pdo->query("SELECT COUNT(*) FROM referral_rewards WHERE status='rewarded'")->fetchColumn(),'rejected'=>(int)$pdo->query("SELECT COUNT(*) FROM referral_rewards WHERE status='rejected'")->fetchColumn(),'amount'=>(float)$pdo->query("SELECT COALESCE(SUM(reward_amount),0) FROM referral_rewards WHERE status='rewarded'")->fetchColumn()];
$titles=['dashboard'=>'数据概览','users'=>'用户管理','recharges'=>'充值审核','withdrawals'=>'提现审核','cards'=>'充值卡','referrals'=>'邀请记录','game'=>'玩法与RTP','settings'=>'系统设置'];$statusNames=['pending'=>'待审核','approved'=>'已到账','rejected'=>'已拒绝','reversed'=>'已冲正','rewarded'=>'已奖励','qualified'=>'关系有效'];
$gameSettings=settings_map();$gameStats=game_window_stats($pdo,(int)($gameSettings['rtp_window']??1000));$specialDefinitions=game_special_definitions($gameSettings);$gameBoard=game_board($gameSettings);$gameProbabilityModel=game_effective_probability_model($gameSettings,$gameStats);
if($view==='game'){require __DIR__.'/game.php';exit;}
?><!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title><?=e($titles[$view])?> - 管理后台</title><link rel="stylesheet" href="/assets/app.css?v=20260721"><link rel="stylesheet" href="/assets/admin.css?v=20260721"></head><body><div class="admin-layout"><aside class="admin-side"><a class="admin-brand" href="/admin/index.php"><span>◆</span><?=e(setting('site_name'))?></a><nav><?php foreach(['dashboard'=>'数据概览','users'=>'用户管理','recharges'=>'充值审核','withdrawals'=>'提现审核','cards'=>'充值卡','referrals'=>'邀请记录','game'=>'玩法与RTP','settings'=>'系统设置'] as $k=>$name):?><a class="<?=$view===$k?'active':''?>" href="/admin/index.php?view=<?=$k?>"><?=e($name)?></a><?php endforeach;?></nav><footer><span>当前管理员:<?=e($admin['username'])?></span><a href="/index.php" target="_blank">查看用户端 ↗</a><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="logout"><button class="mini-btn">退出登录</button></form></footer></aside><div class="admin-main"><header class="admin-top"><h1><?=e($titles[$view])?></h1><span><?=date('Y-m-d H:i')?></span></header><main class="admin-body"><?php if($flash):?><div class="alert <?=e($flash['type'])?>"><?=e($flash['message'])?></div><?php endif;?>
<?php if($view==='dashboard'):?><section class="admin-stats"><article><span>注册用户</span><strong><?=$stats['users']?></strong></article><article><span>待审核充值</span><strong><?=$stats['pending']?></strong></article><article><span>用户余额合计</span><strong>¥<?=number_format($stats['balance'],2)?></strong></article><article><span>今日到账</span><strong>¥<?=number_format($stats['today'],2)?></strong></article></section><section class="panel"><div class="panel-head"><div><h2>最新充值订单</h2><p>优先处理待审核订单</p></div><a href="?view=recharges">全部订单</a></div><?=render_orders($orders,$statusNames)?></section>
<?php elseif($view==='users'):?><section class="panel"><div class="panel-head"><div><h2>用户列表</h2><p>最近 100 个账号</p></div><form class="searchbar"><input type="hidden" name="view" value="users"><input name="q" value="<?=e($_GET['q']??'')?>" placeholder="搜索账号或 ID"><button class="mini-btn">搜索</button></form></div><div class="table-wrap"><table><thead><tr><th>ID</th><th>账号</th><th>手机</th><th>余额</th><th>注册时间</th><th>状态</th><th>余额调整</th><th>操作</th></tr></thead><tbody><?php foreach($users as $u):?><tr><td><?=(int)$u['id']?></td><td><b><?=e($u['username'])?></b></td><td><?=e($u['phone']?:'-')?></td><td>¥<?=number_format((float)$u['balance'],2)?></td><td><?=e($u['created_at'])?></td><td><span class="badge <?= (int)$u['status']===1?'approved':'rejected' ?>"><?= (int)$u['status']===1?'正常':'停用' ?></span></td><td><form class="inline-form" method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="adjust_balance"><input type="hidden" name="return" value="/admin/index.php?view=users"><input type="hidden" name="user_id" value="<?=(int)$u['id']?>"><input type="number" step="0.01" name="amount" placeholder="+/- 金额" required><button class="mini-btn">确定</button></form></td><td><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="toggle_user"><input type="hidden" name="return" value="/admin/index.php?view=users"><input type="hidden" name="user_id" value="<?=(int)$u['id']?>"><input type="hidden" name="status" value="<?= (int)$u['status']===1?0:1 ?>"><button class="mini-btn <?= (int)$u['status']===1?'reject':'approve' ?>"><?= (int)$u['status']===1?'停用':'启用' ?></button></form></td></tr><?php endforeach;?></tbody></table></div></section>
<?php elseif($view==='recharges'):?><section class="panel"><div class="panel-head"><div><h2>充值订单</h2><p>审核通过后系统自动增加用户余额</p></div></div><?=render_orders($orders,$statusNames)?></section>
<?php elseif($view==='withdrawals'):?><section class="panel"><div class="panel-head"><div><h2>提现订单</h2><p>用户提交时已冻结余额,拒绝后自动退回</p></div></div><div class="table-wrap"><table><thead><tr><th>ID</th><th>用户</th><th>金额</th><th>收款账号</th><th>姓名</th><th>时间</th><th>状态</th><th>操作</th></tr></thead><tbody><?php foreach($withdrawals as $w):?><tr><td>#<?=(int)$w['id']?></td><td><?=e($w['username'])?></td><td><b>¥<?=number_format((float)$w['amount'],2)?></b></td><td><?=e($w['account'])?></td><td><?=e($w['real_name'])?></td><td><?=e($w['created_at'])?></td><td><span class="badge <?=e($w['status'])?>"><?=e($statusNames[$w['status']]??$w['status'])?></span></td><td><?php if($w['status']==='pending'):?><div class="admin-actions"><?php foreach(['approved'=>'通过','rejected'=>'拒绝'] as $decision=>$label):?><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="review_withdrawal"><input type="hidden" name="return" value="/admin/index.php?view=withdrawals"><input type="hidden" name="id" value="<?=(int)$w['id']?>"><input type="hidden" name="decision" value="<?=$decision?>"><button class="mini-btn <?=$decision==='approved'?'approve':'reject'?>"><?=$label?></button></form><?php endforeach;?></div><?php else:?>-<?php endif;?></td></tr><?php endforeach;?><?php if(!$withdrawals):?><tr><td colspan="8" class="empty-cell">暂无提现订单</td></tr><?php endif;?></tbody></table></div></section>
<?php elseif($view==='cards'): ?>
<div class="settings-grid">
<section class="panel"><h2>生成充值卡</h2><form method="post" action="/admin/action.php" class="form-stack" data-card-create-form><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="create_cards"><input type="hidden" name="return" value="/admin/index.php?view=cards"><label><span>卡类型</span><select name="card_type" data-card-type><option value="single">普通一次性卡</option><option value="shared">公共卡(每账号一次)</option></select></label><label><span>卡面额</span><input type="number" name="amount" min="1" max="100000" step="0.01" required></label><label><span>生成数量</span><input type="number" name="count" min="1" max="100" value="10" required data-card-count></label><button class="btn primary">生成充值卡</button></form></section>
<section class="panel"><h2>使用说明</h2><p class="card-note">普通卡仅能被一个用户使用一次。公共卡可由所有用户各兑换一次,并可随时停用。请通过安全渠道发放卡号。</p></section>
</div>
<section class="panel card-manager" data-card-manager>
<div class="panel-head"><div><h2>充值卡列表</h2><p>最近 100 张,可复制或导出当前可用卡</p></div><div class="card-batch-actions"><button type="button" class="mini-btn" data-card-select-all>全选可用卡</button><button type="button" class="mini-btn approve" data-card-copy disabled>复制所选</button><button type="button" class="mini-btn" data-card-export disabled>导出 CSV</button><span data-card-selected-count>已选 0 张</span></div></div>
<div class="table-wrap"><table><thead><tr><th class="card-check"><input type="checkbox" data-card-toggle-all aria-label="全选可用充值卡" title="全选可用充值卡"></th><th>卡号</th><th>类型</th><th>面额</th><th>状态</th><th>使用情况</th><th>生成时间</th><th>使用时间</th><th>操作</th></tr></thead><tbody>
<?php foreach($cards as $c): $isShared=($c['card_type']??'single')==='shared'; $selectable=$isShared?$c['status']==='active':$c['status']==='unused'; $selected=$selectable&&in_array((string)$c['code'],$generatedCardCodes,true); $statusLabel=$isShared?($c['status']==='active'?'启用':'停用'):($c['status']==='unused'?'未使用':'已使用'); ?>
<tr class="<?=$selected?'card-new-batch':''?>"><td class="card-check"><input type="checkbox" class="card-select" <?=$selectable?'':'disabled'?> <?=$selected?'checked':''?> data-card-code="<?=e($c['code'])?>" data-card-type="<?=$isShared?'公共卡':'普通卡'?>" data-card-amount="<?=e(number_format((float)$c['amount'],2,'.',''))?>" data-card-status="<?=e($statusLabel)?>" data-card-created="<?=e($c['created_at'])?>" aria-label="选择卡号 <?=e($c['code'])?>"></td><td class="mono"><b><?=e($c['code'])?></b></td><td><span class="badge <?=$isShared?'shared':'pending'?>"><?=$isShared?'公共卡':'普通卡'?></span></td><td>¥<?=number_format((float)$c['amount'],2)?></td><td><span class="badge <?=$selectable?'approved':'rejected'?>"><?=e($statusLabel)?></span></td><td><?=$isShared?(int)$c['redemption_count'].' 人':e($c['username']??'-')?></td><td><?=e($c['created_at'])?></td><td><?=$isShared?'-':e($c['used_at']??'-')?></td><td><?php if($isShared): ?><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="toggle_shared_card"><input type="hidden" name="return" value="/admin/index.php?view=cards"><input type="hidden" name="id" value="<?=(int)$c['id']?>"><input type="hidden" name="status" value="<?=$c['status']==='active'?'disabled':'active'?>"><button class="mini-btn <?=$c['status']==='active'?'reject':'approve'?>"><?=$c['status']==='active'?'停用':'启用'?></button></form><?php else: ?>-<?php endif; ?></td></tr>
<?php endforeach; ?>
<?php if(!$cards): ?><tr><td colspan="9" class="empty-cell">暂无充值卡</td></tr><?php endif; ?>
</tbody></table></div>
</section>
<?php elseif($view==='referrals'):?><section class="admin-stats"><article><span>成功奖励</span><strong><?=$referralStats['rewarded']?></strong></article><article><span>IP 拦截</span><strong><?=$referralStats['rejected']?></strong></article><article><span>累计发放</span><strong>¥<?=number_format($referralStats['amount'],2)?></strong></article><article><span>单人奖励</span><strong>¥<?=number_format((float)setting('invite_reward','0'),2)?></strong></article></section><section class="panel"><div class="panel-head"><div><h2>邀请奖励记录</h2><p>同 IP 自邀或重复领取会自动拦截</p></div></div><div class="table-wrap"><table><thead><tr><th>邀请人</th><th>新用户</th><th>注册 IP</th><th>奖励</th><th>状态</th><th>原因</th><th>时间</th></tr></thead><tbody><?php foreach($referrals as $r):?><tr><td><b><?=e($r['inviter_name'])?></b> (#<?=(int)$r['inviter_id']?>)</td><td><?=e($r['invitee_name'])?> (#<?=(int)$r['invitee_id']?>)</td><td class="mono"><?=e($r['invitee_ip']?:'-')?></td><td>¥<?=number_format((float)$r['reward_amount'],2)?></td><td><span class="badge <?=e($r['status'])?>"><?=e($statusNames[$r['status']]??$r['status'])?></span></td><td><?=e($r['reason']?:'-')?></td><td><?=e($r['created_at'])?></td></tr><?php endforeach;?><?php if(!$referrals):?><tr><td colspan="7" class="empty-cell">暂无邀请记录</td></tr><?php endif;?></tbody></table></div></section>
<?php else:?><div class="settings-grid"><section class="panel"><h2>站点参数</h2><form method="post" action="/admin/action.php" class="form-stack"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="settings"><input type="hidden" name="return" value="/admin/index.php?view=settings"><label><span>站点名称</span><input name="site_name" value="<?=e(setting('site_name'))?>" required></label><label><span>站点公告</span><input name="announcement" value="<?=e(setting('announcement'))?>"></label><label><span>客服微信</span><input name="customer_service" value="<?=e(setting('customer_service'))?>"></label><label><span>充值说明</span><input name="recharge_instructions" value="<?=e(setting('recharge_instructions'))?>"></label><label><span>注册赠送余额</span><input type="number" min="0" step="0.01" name="register_bonus" value="<?=e(setting('register_bonus'))?>"></label><label><span>单人邀请奖励</span><input type="number" min="0" max="1000000" step="0.01" name="invite_reward" value="<?=e(setting('invite_reward','100'))?>" required></label><label><span>一级下线充值佣金 (%)</span><input type="number" min="0" max="100" step="0.0001" name="direct_commission_rate" value="<?=e(setting('direct_commission_rate','10'))?>" required></label><label><span>二级下线充值佣金 (%)</span><input type="number" min="0" max="100" step="0.0001" name="second_commission_rate" value="<?=e(setting('second_commission_rate','1'))?>" required></label><label><span>游戏开关</span><select name="game_enabled"><option value="1" <?=setting('game_enabled')==='1'?'selected':''?>>开启</option><option value="0" <?=setting('game_enabled')==='0'?'selected':''?>>关闭</option></select></label><button class="btn primary">保存站点设置</button></form></section><section class="panel"><h2>管理员密码</h2><form method="post" action="/admin/action.php" class="form-stack"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="admin_password"><input type="hidden" name="return" value="/admin/index.php?view=settings"><label><span>原密码</span><input type="password" name="old_password" required></label><label><span>新密码</span><input type="password" name="new_password" minlength="10" required></label><button class="btn primary">更新管理员密码</button></form></section></div><?php endif;?></main></div></div><script src="/assets/app.js?v=20260722-cards2"></script></body></html>
<?php
function render_orders(array $orders, array $statusNames): string
{
ob_start(); ?>
<div class="table-wrap"><table><thead><tr><th>订单号</th><th>用户</th><th>金额</th><th>方式</th><th>付款备注</th><th>时间</th><th>状态</th><th>操作</th></tr></thead><tbody>
<?php foreach($orders as $o): ?><tr>
<td class="mono"><?=e($o['order_no'])?></td><td><?=e($o['username'])?> (#<?=(int)$o['user_id']?>)</td><td><b>¥<?=number_format((float)$o['amount'],2)?></b></td><td><?=e($o['method'])?></td><td class="admin-note" title="<?=e($o['payer_note'])?>"><?=e($o['payer_note']?:'-')?></td><td><?=e($o['created_at'])?></td><td><span class="badge <?=e($o['status'])?>"><?=e($statusNames[$o['status']]??$o['status'])?></span></td>
<td><?php if($o['status']==='pending'): ?><div class="admin-actions">
<?php foreach(['approved'=>'通过','rejected'=>'拒绝'] as $decision=>$label): ?><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="review_recharge"><input type="hidden" name="return" value="/admin/index.php?view=recharges"><input type="hidden" name="id" value="<?=(int)$o['id']?>"><input type="hidden" name="decision" value="<?=$decision?>"><button class="mini-btn <?=$decision==='approved'?'approve':'reject'?>"><?=$label?></button></form><?php endforeach; ?>
</div><?php elseif($o['status']==='approved'): ?><form class="inline-form" method="post" action="/admin/action.php" onsubmit="return confirm('确认冲正该笔充值及其推广佣金?')"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="reverse_recharge"><input type="hidden" name="return" value="/admin/index.php?view=recharges"><input type="hidden" name="id" value="<?=(int)$o['id']?>"><input name="note" maxlength="200" placeholder="冲正原因" required><button class="mini-btn reject">冲正</button></form><?php else: ?>-<?php endif; ?></td>
</tr><?php endforeach; ?>
<?php if(!$orders): ?><tr><td colspan="8" class="empty-cell">暂无订单</td></tr><?php endif; ?></tbody></table></div>
<?php return (string) ob_get_clean();
}