- 拆分 HomeController → TransactionController, ReportWebController, FollowPlanController - 新增 Service 层: TransactionService, ReportService, FollowPlanService - pk10.php JS 抽离为 4 个独立文件 (sound/race/bet/poll) - 前台新增报表查询页面 (/report) + 跟单计划页面 (/follow-plan) - 后台新增跟单计划管理 + 用户输赢明细统计 - 封盘状态显示倒计时 (x:xx) - 音效仅在开奖弹窗打开时播放 - 路由按模块分组整理 - autoload 支持 App\Services 命名空间
144 lines
5.6 KiB
PHP
144 lines
5.6 KiB
PHP
<?php
|
||
namespace App\Controllers\Admin;
|
||
|
||
use App\Core\AdminBaseController;
|
||
use Db\Database;
|
||
|
||
class ReportController extends AdminBaseController {
|
||
private $db;
|
||
public function __construct(Database $db) { $this->db = $db; }
|
||
|
||
public function index() {
|
||
$this->checkLogin(); $this->checkAdmin();
|
||
$dateFrom = $_GET['from'] ?? date('Y-m-d', strtotime('-7 days'));
|
||
$dateTo = $_GET['to'] ?? date('Y-m-d');
|
||
|
||
$reportService = new \App\Services\ReportService($this->db);
|
||
|
||
// 总体统计
|
||
$overview = $reportService->getOverviewStats($dateFrom, $dateTo);
|
||
extract($overview); // totalBet, totalWin, profit, profitRate, totalDeposit, totalWithdraw, totalCommission, totalRebate, totalUsers, newUsers, activeUsers
|
||
|
||
// 日明细统计
|
||
$dailyStats = $reportService->getDailyStats($dateFrom, $dateTo);
|
||
|
||
// 用户排行(投注前20)
|
||
$topUsers = $reportService->getTopUsers($dateFrom, $dateTo, 20);
|
||
|
||
// 代理报表
|
||
$agentStats = $reportService->getAgentStats($dateFrom, $dateTo);
|
||
|
||
// 用户输赢明细
|
||
$winLossData = $reportService->getUserWinLoss($dateFrom, $dateTo);
|
||
$userSummary = $winLossData['summary'];
|
||
|
||
$this->render('Admin/reports.php', compact(
|
||
'dateFrom','dateTo','totalBet','totalWin','profit','profitRate',
|
||
'totalDeposit','totalWithdraw','totalCommission','totalRebate',
|
||
'totalUsers','newUsers','activeUsers','dailyStats','topUsers','agentStats',
|
||
'userSummary'
|
||
));
|
||
}
|
||
|
||
/**
|
||
* CSV 导出
|
||
*/
|
||
public function export() {
|
||
$this->checkLogin(); $this->checkAdmin();
|
||
$dateFrom = $_GET['from'] ?? date('Y-m-d', strtotime('-7 days'));
|
||
$dateTo = $_GET['to'] ?? date('Y-m-d');
|
||
|
||
$reportService = new \App\Services\ReportService($this->db);
|
||
|
||
// 通过 Service 获取数据
|
||
$dailyStats = $reportService->getDailyStats($dateFrom, $dateTo);
|
||
$topUsers = $reportService->getTopUsers($dateFrom, $dateTo, 0); // 不限条数
|
||
$winLossData = $reportService->getUserWinLoss($dateFrom, $dateTo);
|
||
$userSummary = $winLossData['summary'];
|
||
$userWinLossRaw = $winLossData['raw'];
|
||
|
||
// 输出 CSV
|
||
header('Content-Type: text/csv; charset=utf-8');
|
||
header('Content-Disposition: attachment; filename="report_' . $dateFrom . '_' . $dateTo . '.csv"');
|
||
// BOM 头(Excel 兼容中文)
|
||
echo "\xEF\xBB\xBF";
|
||
$out = fopen('php://output', 'w');
|
||
|
||
// 日明细
|
||
fputcsv($out, ['=== 日明细报表 ===']);
|
||
fputcsv($out, ['日期', '投注额', '派彩额', '利润', '投注笔数', '中奖笔数', '胜率']);
|
||
foreach ($dailyStats as $day) {
|
||
$totalBet = floatval($day['total_bet'] ?? 0);
|
||
$totalWin = floatval($day['total_win'] ?? 0);
|
||
$betCount = intval($day['bet_count'] ?? 0);
|
||
$winCount = intval($day['win_count'] ?? 0);
|
||
$winRate = $betCount > 0 ? round($winCount / $betCount * 100, 1) . '%' : '0%';
|
||
fputcsv($out, [
|
||
$day['date'],
|
||
number_format($totalBet, 2, '.', ''),
|
||
number_format($totalWin, 2, '.', ''),
|
||
number_format($totalBet - $totalWin, 2, '.', ''),
|
||
$betCount,
|
||
$winCount,
|
||
$winRate
|
||
]);
|
||
}
|
||
|
||
fputcsv($out, []);
|
||
fputcsv($out, ['=== 用户投注排行 ===']);
|
||
fputcsv($out, ['排名', '用户名', '投注额', '派彩额', '平台盈亏', '投注笔数']);
|
||
$rank = 1;
|
||
foreach ($topUsers as $user) {
|
||
fputcsv($out, [
|
||
$rank++,
|
||
$user['username'],
|
||
number_format(floatval($user['total_bet']), 2, '.', ''),
|
||
number_format(floatval($user['total_win']), 2, '.', ''),
|
||
number_format(floatval($user['profit']), 2, '.', ''),
|
||
intval($user['bet_count'])
|
||
]);
|
||
}
|
||
|
||
// 用户输赢明细
|
||
fputcsv($out, []);
|
||
fputcsv($out, ['=== 用户输赢明细 ===']);
|
||
fputcsv($out, ['用户名', '当前余额', '总投注', '总派彩', '平台盈亏(投注-派彩)', '投注笔数', '中奖笔数', '胜率']);
|
||
foreach ($userSummary as $ud) {
|
||
$tb = $ud['total_bet'];
|
||
$tw = $ud['total_win'];
|
||
$bc = $ud['bet_count'];
|
||
$wc = $ud['win_count'];
|
||
$wr = $bc > 0 ? round($wc / $bc * 100, 1) . '%' : '0%';
|
||
fputcsv($out, [
|
||
$ud['username'],
|
||
number_format($ud['balance'], 2, '.', ''),
|
||
number_format($tb, 2, '.', ''),
|
||
number_format($tw, 2, '.', ''),
|
||
number_format($tb - $tw, 2, '.', ''),
|
||
$bc, $wc, $wr
|
||
]);
|
||
}
|
||
|
||
// 用户日输赢明细
|
||
fputcsv($out, []);
|
||
fputcsv($out, ['=== 用户日输赢明细 ===']);
|
||
fputcsv($out, ['用户名', '日期', '投注额', '派彩额', '平台盈亏', '笔数']);
|
||
foreach ($userWinLossRaw as $dd) {
|
||
$tb = floatval($dd['total_bet']);
|
||
$tw = floatval($dd['total_win']);
|
||
fputcsv($out, [
|
||
$dd['username'], $dd['date'],
|
||
number_format($tb, 2, '.', ''),
|
||
number_format($tw, 2, '.', ''),
|
||
number_format($tb - $tw, 2, '.', ''),
|
||
intval($dd['bet_count'])
|
||
]);
|
||
}
|
||
|
||
fclose($out);
|
||
exit;
|
||
}
|
||
|
||
private function json($data) { header('Content-Type: application/json'); echo json_encode($data); }
|
||
}
|