Explorar o código

update:每日数据

aiden hai 3 meses
pai
achega
489ad27a69

+ 376 - 0
app/controller/DailyStatistics.php

@@ -0,0 +1,376 @@
+<?php
+declare (strict_types = 1);
+
+namespace app\controller;
+
+use app\BaseController;
+use app\model\MerchantDailyModel;
+use app\model\GameDailyModel;
+use app\model\MerchantHistoryModel;
+use think\facade\Request;
+
+class DailyStatistics extends BaseController
+{
+    /**
+     * 获取商户每日数据列表
+     */
+    public function merchantDailyList()
+    {
+        $userInfo = $this->request->userInfo;
+        
+        // 获取查询参数
+        $page = Request::get('page', 1, 'intval');
+        $limit = Request::get('limit', 10, 'intval');
+        $startDate = Request::get('start_date', date('Y-m-d', strtotime('-7 days')), 'trim');
+        $endDate = Request::get('end_date', date('Y-m-d'), 'trim');
+        
+        try {
+            // 获取商户每日数据
+            $result = MerchantDailyModel::getMerchantDailyList(
+                $userInfo['merchant_id'],
+                $startDate,
+                $endDate,
+                $page,
+                $limit
+            );
+            
+            // 格式化数据
+            foreach ($result['list'] as &$item) {
+                $item['game_profit'] = round($item['game_profit'], 2);
+                $item['bet_amount'] = round($item['bet_amount'], 2);
+                $item['commission_amount'] = round($item['commission_amount'], 2);
+                $item['platform_fee'] = round($item['platform_fee'], 2);
+                $item['merchant_name'] = $userInfo['merchant_name'] ?? '商户' . $userInfo['merchant_id'];
+            }
+            
+            return json_success($result, '获取成功');
+        } catch (\Exception $e) {
+            return json_error([], '获取商户每日数据失败:' . $e->getMessage());
+        }
+    }
+    
+    /**
+     * 获取游戏每日数据列表
+     */
+    public function gameDailyList()
+    {
+        $userInfo = $this->request->userInfo;
+        
+        // 获取查询参数
+        $page = Request::get('page', 1, 'intval');
+        $limit = Request::get('limit', 10, 'intval');
+        $gameId = Request::get('game_id', 0, 'intval');
+        $gameName = Request::get('game_name', '', 'trim');
+        $startDate = Request::get('start_date', date('Y-m-d', strtotime('-7 days')), 'trim');
+        $endDate = Request::get('end_date', date('Y-m-d'), 'trim');
+        
+        $filters = [
+            'merchant_id' => $userInfo['merchant_id'],
+            'game_id' => $gameId,
+            'game_name' => $gameName,
+            'start_date' => $startDate,
+            'end_date' => $endDate
+        ];
+        
+        try {
+            // 获取游戏每日数据
+            $result = GameDailyModel::getGameDailyList($filters, $page, $limit);
+            
+            // 格式化数据
+            foreach ($result['list'] as &$item) {
+                $item['game_profit'] = round($item['game_profit'], 2);
+                $item['bet_amount'] = round($item['bet_amount'], 2);
+                $item['commission_amount'] = round($item['commission_amount'], 2);
+            }
+            
+            return json_success($result, '获取成功');
+        } catch (\Exception $e) {
+            return json_error([], '获取游戏每日数据失败:' . $e->getMessage());
+        }
+    }
+    
+    /**
+     * 获取商户汇总统计
+     */
+    public function merchantSummary()
+    {
+        $userInfo = $this->request->userInfo;
+        
+        $startDate = Request::get('start_date', date('Y-m-d', strtotime('-30 days')), 'trim');
+        $endDate = Request::get('end_date', date('Y-m-d'), 'trim');
+        
+        try {
+            $summary = MerchantDailyModel::getMerchantSummary(
+                $userInfo['merchant_id'],
+                $startDate,
+                $endDate
+            );
+            
+            return json_success($summary, '获取成功');
+        } catch (\Exception $e) {
+            return json_error([], '获取商户汇总统计失败:' . $e->getMessage());
+        }
+    }
+    
+    /**
+     * 获取游戏列表
+     */
+    public function getGameList()
+    {
+        $userInfo = $this->request->userInfo;
+        
+        try {
+            $games = GameDailyModel::getGameList($userInfo['merchant_id']);
+            
+            return json_success($games, '获取成功');
+        } catch (\Exception $e) {
+            return json_error([], '获取游戏列表失败:' . $e->getMessage());
+        }
+    }
+    
+    /**
+     * 获取商户历史数据统计
+     */
+    public function merchantHistory()
+    {
+        $userInfo = $this->request->userInfo;
+        
+        // 获取过滤参数
+        $filters = [
+            'start_date' => Request::get('start_date', '', 'trim'),
+            'end_date' => Request::get('end_date', '', 'trim')
+        ];
+        
+        try {
+            $history = MerchantHistoryModel::getMerchantHistoryStatistics(
+                $userInfo['merchant_id'],
+                $filters
+            );
+            
+            return json_success($history, '获取成功');
+        } catch (\Exception $e) {
+            return json_error([], '获取商户历史数据失败:' . $e->getMessage());
+        }
+    }
+    
+    /**
+     * 获取商户历史数据列表(按月或按天)
+     */
+    public function merchantHistoryList()
+    {
+        $userInfo = $this->request->userInfo;
+        
+        // 获取查询参数
+        $page = Request::get('page', 1, 'intval');
+        $limit = Request::get('limit', 10, 'intval');
+        $groupBy = Request::get('group_by', 'month', 'trim'); // month 或 day
+        
+        $filters = [
+            'start_date' => Request::get('start_date', '', 'trim'),
+            'end_date' => Request::get('end_date', '', 'trim')
+        ];
+        
+        try {
+            $result = MerchantHistoryModel::getMerchantHistoryList(
+                $userInfo['merchant_id'],
+                $groupBy,
+                $page,
+                $limit,
+                $filters
+            );
+            
+            return json_success($result, '获取成功');
+        } catch (\Exception $e) {
+            return json_error([], '获取商户历史数据列表失败:' . $e->getMessage());
+        }
+    }
+    
+    /**
+     * 导出商户历史数据
+     */
+    public function exportMerchantHistory()
+    {
+        $userInfo = $this->request->userInfo;
+        
+        $groupBy = Request::get('group_by', 'month', 'trim');
+        $filters = [
+            'start_date' => Request::get('start_date', '', 'trim'),
+            'end_date' => Request::get('end_date', '', 'trim')
+        ];
+        
+        try {
+            // 获取所有数据
+            $result = MerchantHistoryModel::getMerchantHistoryList(
+                $userInfo['merchant_id'],
+                $groupBy,
+                1,
+                100000,
+                $filters
+            );
+            
+            // 生成CSV数据
+            $csvData = "时间,RTP(%),注单数,注单金额(THB),游戏输赢(THB),注单金额(USDT),游戏输赢(USDT),登录用户,注册用户,投注用户,抽水额度(USDT),购买免费游戏次数\n";
+            
+            foreach ($result['list'] as $item) {
+                $csvData .= sprintf(
+                    "%s,%.2f,%d,%.2f,%.2f,%.4f,%.4f,%d,%d,%d,%.4f,%d\n",
+                    $item['period'],
+                    $item['rtp'],
+                    $item['total_orders'],
+                    $item['total_bet_thb'],
+                    $item['game_profit_thb'],
+                    $item['total_bet_usdt'],
+                    $item['game_profit_usdt'],
+                    $item['login_users'],
+                    $item['register_users'],
+                    $item['bet_users'],
+                    $item['commission_usdt'],
+                    $item['free_game_count']
+                );
+            }
+            
+            // 返回CSV数据
+            return response($csvData)
+                ->header(['Content-Type' => 'text/csv; charset=utf-8'])
+                ->header(['Content-Disposition' => 'attachment; filename="merchant_history_' . date('YmdHis') . '.csv"'])
+                ->header(['Cache-Control' => 'no-cache, must-revalidate']);
+                
+        } catch (\Exception $e) {
+            return json_error([], '导出商户历史数据失败:' . $e->getMessage());
+        }
+    }
+    
+    /**
+     * 获取游戏汇总统计
+     */
+    public function gameSummary()
+    {
+        $userInfo = $this->request->userInfo;
+        
+        $startDate = Request::get('start_date', date('Y-m-d', strtotime('-30 days')), 'trim');
+        $endDate = Request::get('end_date', date('Y-m-d'), 'trim');
+        
+        try {
+            $summary = GameDailyModel::getGameSummary(
+                $userInfo['merchant_id'],
+                $startDate,
+                $endDate
+            );
+            
+            // 格式化数据
+            foreach ($summary as &$item) {
+                $item['total_profit'] = round($item['total_profit'], 2);
+                $item['avg_rtp'] = round($item['avg_rtp'], 2);
+                $item['total_bet_amount'] = round($item['total_bet_amount'], 2);
+                $item['total_commission'] = round($item['total_commission'], 2);
+            }
+            
+            return json_success($summary, '获取成功');
+        } catch (\Exception $e) {
+            return json_error([], '获取游戏汇总统计失败:' . $e->getMessage());
+        }
+    }
+    
+    /**
+     * 导出商户每日数据
+     */
+    public function exportMerchantDaily()
+    {
+        $userInfo = $this->request->userInfo;
+        
+        $startDate = Request::get('start_date', date('Y-m-d', strtotime('-30 days')), 'trim');
+        $endDate = Request::get('end_date', date('Y-m-d'), 'trim');
+        
+        try {
+            // 获取所有数据
+            $result = MerchantDailyModel::getMerchantDailyList(
+                $userInfo['merchant_id'],
+                $startDate,
+                $endDate,
+                1,
+                100000
+            );
+            
+            // 生成CSV数据
+            $csvData = "日期,商户,游戏输赢,游戏RTP(%),注单金额,注单数,投注用户,注册用户,登录用户,抽水额度,平台费用(USDT),购买免费游戏次数\n";
+            
+            foreach ($result['list'] as $item) {
+                $csvData .= sprintf(
+                    "%s,%s,%.2f,%.2f,%.2f,%d,%d,%d,%d,%.2f,%.2f,%d\n",
+                    $item['date'],
+                    $userInfo['merchant_name'] ?? '商户' . $userInfo['merchant_id'],
+                    $item['game_profit'],
+                    $item['game_rtp'],
+                    $item['bet_amount'],
+                    $item['bet_count'],
+                    $item['bet_users'],
+                    $item['register_users'],
+                    $item['login_users'],
+                    $item['commission_amount'],
+                    $item['platform_fee'],
+                    $item['free_game_count']
+                );
+            }
+            
+            // 返回CSV数据
+            return response($csvData)
+                ->header(['Content-Type' => 'text/csv; charset=utf-8'])
+                ->header(['Content-Disposition' => 'attachment; filename="merchant_daily_' . date('YmdHis') . '.csv"'])
+                ->header(['Cache-Control' => 'no-cache, must-revalidate']);
+                
+        } catch (\Exception $e) {
+            return json_error([], '导出商户每日数据失败:' . $e->getMessage());
+        }
+    }
+    
+    /**
+     * 导出游戏每日数据
+     */
+    public function exportGameDaily()
+    {
+        $userInfo = $this->request->userInfo;
+        
+        $startDate = Request::get('start_date', date('Y-m-d', strtotime('-30 days')), 'trim');
+        $endDate = Request::get('end_date', date('Y-m-d'), 'trim');
+        
+        $filters = [
+            'merchant_id' => $userInfo['merchant_id'],
+            'start_date' => $startDate,
+            'end_date' => $endDate
+        ];
+        
+        try {
+            // 获取所有数据
+            $result = GameDailyModel::getGameDailyList($filters, 1, 100000);
+            
+            // 生成CSV数据
+            $csvData = "日期,游戏名称,游戏输赢,游戏RTP(%),注单金额,注单数,投注用户,注册用户,登录用户,抽水额度,购买免费游戏次数\n";
+            
+            foreach ($result['list'] as $item) {
+                $csvData .= sprintf(
+                    "%s,%s,%.2f,%.2f,%.2f,%d,%d,%d,%d,%.2f,%d\n",
+                    $item['date'],
+                    $item['game_name'],
+                    $item['game_profit'],
+                    $item['game_rtp'],
+                    $item['bet_amount'],
+                    $item['bet_count'],
+                    $item['bet_users'],
+                    $item['register_users'],
+                    $item['login_users'],
+                    $item['commission_amount'],
+                    $item['free_game_count']
+                );
+            }
+            
+            // 返回CSV数据
+            return response($csvData)
+                ->header(['Content-Type' => 'text/csv; charset=utf-8'])
+                ->header(['Content-Disposition' => 'attachment; filename="game_daily_' . date('YmdHis') . '.csv"'])
+                ->header(['Cache-Control' => 'no-cache, must-revalidate']);
+                
+        } catch (\Exception $e) {
+            return json_error([], '导出游戏每日数据失败:' . $e->getMessage());
+        }
+    }
+}

+ 245 - 0
app/model/GameDailyModel.php

@@ -0,0 +1,245 @@
+<?php
+declare (strict_types = 1);
+
+namespace app\model;
+
+use think\Model;
+use think\facade\Db;
+
+/**
+ * 游戏每日数据统计模型 - 基于tp_game_bet_order表实时统计
+ */
+class GameDailyModel extends Model
+{
+    // 连接到fortue_tiger数据库
+    protected $connection = 'fortue_tiger';
+    
+    /**
+     * 获取游戏每日数据列表
+     */
+    public static function getGameDailyList($filters = [], $page = 1, $limit = 10)
+    {
+        $query = Db::connect('fortue_tiger')->name('game_bet_order');
+        
+        // 应用过滤条件
+        if (!empty($filters['merchant_id'])) {
+            $query->where('app_id', $filters['merchant_id']);
+        }
+        
+        // 日期范围
+        $startDate = $filters['start_date'] ?? date('Y-m-d', strtotime('-7 days'));
+        $endDate = $filters['end_date'] ?? date('Y-m-d');
+        $startTime = strtotime($startDate . ' 00:00:00');
+        $endTime = strtotime($endDate . ' 23:59:59');
+        
+        $query->where('create_time', '>=', $startTime)
+              ->where('create_time', '<=', $endTime)
+              ->where('status', 1); // 只统计有效订单
+        
+        // 游戏ID或名称过滤
+        if (!empty($filters['game_id'])) {
+            $query->where('game_id', $filters['game_id']);
+        }
+        
+        if (!empty($filters['game_name'])) {
+            // 如果有游戏名称表,可以关联查询
+            $query->where('game_id', 'like', '%' . $filters['game_name'] . '%');
+        }
+        
+        // 按游戏和日期分组统计
+        $sql = "SELECT 
+                    DATE_FORMAT(FROM_UNIXTIME(create_time), '%Y-%m-%d') as date,
+                    game_id,
+                    COUNT(DISTINCT uname) as bet_users,
+                    COUNT(id) as bet_count,
+                    SUM(bet) as bet_amount,
+                    SUM(amount) as game_profit,
+                    SUM(total_win_amount) as total_win,
+                    COUNT(DISTINCT CASE WHEN action_type = 5 THEN id END) as free_game_count
+                FROM tp_game_bet_order
+                WHERE app_id = ? 
+                    AND create_time >= ? 
+                    AND create_time <= ?
+                    AND status = 1";
+        
+        $params = [$filters['merchant_id'] ?? 0, $startTime, $endTime];
+        
+        if (!empty($filters['game_id'])) {
+            $sql .= " AND game_id = ?";
+            $params[] = $filters['game_id'];
+        }
+        
+        $sql .= " GROUP BY date, game_id
+                  ORDER BY date DESC, game_id ASC";
+        
+        // 获取总数(用于分页)
+        $countSql = "SELECT COUNT(DISTINCT CONCAT(DATE_FORMAT(FROM_UNIXTIME(create_time), '%Y-%m-%d'), '-', game_id)) as total
+                     FROM tp_game_bet_order
+                     WHERE app_id = ? 
+                         AND create_time >= ? 
+                         AND create_time <= ?
+                         AND status = 1";
+        
+        $countParams = [$filters['merchant_id'] ?? 0, $startTime, $endTime];
+        if (!empty($filters['game_id'])) {
+            $countSql .= " AND game_id = ?";
+            $countParams[] = $filters['game_id'];
+        }
+        
+        $total = Db::connect('fortue_tiger')->query($countSql, $countParams)[0]['total'] ?? 0;
+        
+        // 添加分页
+        $sql .= " LIMIT " . (($page - 1) * $limit) . ", " . $limit;
+        
+        $list = Db::connect('fortue_tiger')->query($sql, $params);
+        
+        // 处理每条记录
+        foreach ($list as &$item) {
+            // 计算RTP
+            $item['game_rtp'] = 0;
+            if ($item['bet_amount'] > 0) {
+                $item['game_rtp'] = round(($item['total_win'] / $item['bet_amount']) * 100, 2);
+            }
+            
+            // 获取该游戏该天的注册用户(新用户首次玩该游戏)
+            $dayStart = strtotime($item['date'] . ' 00:00:00');
+            $dayEnd = strtotime($item['date'] . ' 23:59:59');
+            
+            $registerUsers = Db::connect('fortue_tiger')
+                ->name('game_bet_order')
+                ->alias('gbo')
+                ->join('tp_merchants_user mu', 'gbo.uname = mu.uname', 'INNER')
+                ->where('gbo.app_id', $filters['merchant_id'] ?? 0)
+                ->where('gbo.game_id', $item['game_id'])
+                ->where('gbo.create_time', '>=', $dayStart)
+                ->where('gbo.create_time', '<=', $dayEnd)
+                ->where('mu.create_time', '>=', $dayStart)
+                ->where('mu.create_time', '<=', $dayEnd)
+                ->count('DISTINCT gbo.uname');
+            
+            // 获取登录用户数
+            $loginUsers = Db::connect('fortue_tiger')
+                ->name('game_bet_order')
+                ->alias('gbo')
+                ->join('tp_merchants_user mu', 'gbo.uname = mu.uname', 'INNER')
+                ->where('gbo.app_id', $filters['merchant_id'] ?? 0)
+                ->where('gbo.game_id', $item['game_id'])
+                ->where('gbo.create_time', '>=', $dayStart)
+                ->where('gbo.create_time', '<=', $dayEnd)
+                ->where('mu.login_time', '>=', $dayStart)
+                ->where('mu.login_time', '<=', $dayEnd)
+                ->count('DISTINCT gbo.uname');
+            
+            // 计算抽水额度
+            $item['commission_amount'] = ($item['bet_amount'] - $item['total_win']) / 100;
+            
+            // 格式化金额字段(转换为元)
+            $item['game_profit'] = abs($item['game_profit']) / 100;
+            $item['bet_amount'] = $item['bet_amount'] / 100;
+            $item['total_win'] = $item['total_win'] / 100;
+            
+            // 添加其他字段
+            $item['game_name'] = '游戏' . $item['game_id']; // 如果有游戏名称表可以关联查询
+            $item['register_users'] = $registerUsers;
+            $item['login_users'] = $loginUsers;
+            
+            // 移除不需要的字段
+            unset($item['total_win']);
+        }
+        
+        return [
+            'list' => $list,
+            'total' => $total,
+            'page' => $page,
+            'limit' => $limit
+        ];
+    }
+    
+    /**
+     * 获取游戏汇总统计
+     */
+    public static function getGameSummary($merchantId, $startDate, $endDate)
+    {
+        $startTime = strtotime($startDate . ' 00:00:00');
+        $endTime = strtotime($endDate . ' 23:59:59');
+        
+        $sql = "SELECT 
+                    game_id,
+                    COUNT(DISTINCT uname) as total_bet_users,
+                    COUNT(id) as total_bet_count,
+                    SUM(bet) as total_bet_amount,
+                    SUM(amount) as total_game_profit,
+                    SUM(total_win_amount) as total_win_amount,
+                    COUNT(DISTINCT CASE WHEN action_type = 5 THEN id END) as total_free_games,
+                    COUNT(DISTINCT DATE_FORMAT(FROM_UNIXTIME(create_time), '%Y-%m-%d')) as active_days
+                FROM tp_game_bet_order
+                WHERE app_id = ? 
+                    AND create_time >= ? 
+                    AND create_time <= ?
+                    AND status = 1
+                GROUP BY game_id
+                ORDER BY total_bet_amount DESC";
+        
+        $list = Db::connect('fortue_tiger')->query($sql, [$merchantId, $startTime, $endTime]);
+        
+        foreach ($list as &$item) {
+            // 计算平均RTP
+            $item['avg_rtp'] = 0;
+            if ($item['total_bet_amount'] > 0) {
+                $item['avg_rtp'] = round(($item['total_win_amount'] / $item['total_bet_amount']) * 100, 2);
+            }
+            
+            // 计算总抽水
+            $item['total_commission'] = ($item['total_bet_amount'] - $item['total_win_amount']) / 100;
+            
+            // 格式化金额字段
+            $item['total_game_profit'] = abs($item['total_game_profit']) / 100;
+            $item['total_bet_amount'] = $item['total_bet_amount'] / 100;
+            $item['total_win_amount'] = $item['total_win_amount'] / 100;
+            
+            // 添加游戏名称
+            $item['game_name'] = '游戏' . $item['game_id'];
+            
+            // 获取该游戏期间的注册和登录用户
+            $item['total_register_users'] = Db::connect('fortue_tiger')
+                ->name('game_bet_order')
+                ->alias('gbo')
+                ->join('tp_merchants_user mu', 'gbo.uname = mu.uname', 'INNER')
+                ->where('gbo.app_id', $merchantId)
+                ->where('gbo.game_id', $item['game_id'])
+                ->where('gbo.create_time', '>=', $startTime)
+                ->where('gbo.create_time', '<=', $endTime)
+                ->where('mu.create_time', '>=', $startTime)
+                ->where('mu.create_time', '<=', $endTime)
+                ->count('DISTINCT gbo.uname');
+            
+            $item['total_login_users'] = Db::connect('fortue_tiger')
+                ->name('game_bet_order')
+                ->alias('gbo')
+                ->join('tp_merchants_user mu', 'gbo.uname = mu.uname', 'INNER')
+                ->where('gbo.app_id', $merchantId)
+                ->where('gbo.game_id', $item['game_id'])
+                ->where('gbo.create_time', '>=', $startTime)
+                ->where('gbo.create_time', '<=', $endTime)
+                ->where('mu.login_time', '>=', $startTime)
+                ->where('mu.login_time', '<=', $endTime)
+                ->count('DISTINCT gbo.uname');
+        }
+        
+        return $list;
+    }
+    
+    /**
+     * 获取所有游戏列表
+     */
+    public static function getGameList($merchantId)
+    {
+        return Db::connect('fortue_tiger')
+            ->name('game_bet_order')
+            ->where('app_id', $merchantId)
+            ->group('game_id')
+            ->field('game_id, COUNT(id) as play_count')
+            ->order('play_count', 'desc')
+            ->select();
+    }
+}

+ 198 - 0
app/model/MerchantDailyModel.php

@@ -0,0 +1,198 @@
+<?php
+declare (strict_types = 1);
+
+namespace app\model;
+
+use think\Model;
+use think\facade\Db;
+
+/**
+ * 商户每日数据统计模型 - 基于tp_game_bet_order表实时统计
+ */
+class MerchantDailyModel extends Model
+{
+    // 连接到fortue_tiger数据库
+    protected $connection = 'fortue_tiger';
+    
+    /**
+     * 获取商户每日数据列表
+     * @param int $merchantId 商户ID
+     * @param string $startDate 开始日期
+     * @param string $endDate 结束日期
+     * @param int $page 页码
+     * @param int $limit 每页数量
+     */
+    public static function getMerchantDailyList($merchantId, $startDate, $endDate, $page = 1, $limit = 10)
+    {
+        $startTime = strtotime($startDate . ' 00:00:00');
+        $endTime = strtotime($endDate . ' 23:59:59');
+        
+        // 生成日期数组
+        $dates = [];
+        $current = $startTime;
+        while ($current <= $endTime) {
+            $dates[] = date('Y-m-d', $current);
+            $current += 86400;
+        }
+        
+        // 按日期分组统计
+        $offset = ($page - 1) * $limit;
+        $paginatedDates = array_slice($dates, $offset, $limit);
+        
+        $list = [];
+        foreach ($paginatedDates as $date) {
+            $dayStart = strtotime($date . ' 00:00:00');
+            $dayEnd = strtotime($date . ' 23:59:59');
+            
+            // 获取游戏下注统计数据
+            $betStats = Db::connect('fortue_tiger')
+                ->name('game_bet_order')
+                ->where('app_id', $merchantId)
+                ->where('create_time', '>=', $dayStart)
+                ->where('create_time', '<=', $dayEnd)
+                ->where('status', 1) // 只统计有效订单
+                ->field([
+                    'COUNT(DISTINCT uname) as bet_users',  // 投注用户数
+                    'COUNT(id) as bet_count',  // 注单数
+                    'SUM(bet) as bet_amount',  // 注单金额(下注分数)
+                    'SUM(amount) as game_profit',  // 游戏输赢(金额变化)
+                    'SUM(total_win_amount) as total_win',  // 总赢得金额
+                    'COUNT(DISTINCT game_id) as game_count'  // 游戏数量
+                ])
+                ->find();
+            
+            // 计算RTP(Return to Player)
+            $rtp = 0;
+            if ($betStats['bet_amount'] > 0) {
+                // RTP = (返还给玩家的金额 / 投注总额) * 100
+                $rtp = round(($betStats['total_win'] / $betStats['bet_amount']) * 100, 2);
+            }
+            
+            // 获取注册用户数
+            $registerUsers = Db::connect('fortue_tiger')
+                ->name('merchants_user')
+                ->where('app_id', $merchantId)
+                ->where('create_time', '>=', $dayStart)
+                ->where('create_time', '<=', $dayEnd)
+                ->count();
+            
+            // 获取登录用户数
+            $loginUsers = Db::connect('fortue_tiger')
+                ->name('merchants_user')
+                ->where('app_id', $merchantId)
+                ->where('login_time', '>=', $dayStart)
+                ->where('login_time', '<=', $dayEnd)
+                ->count();
+            
+            // 计算抽水额度(平台盈利 = 下注金额 - 赢得金额)
+            $commission = ($betStats['bet_amount'] ?? 0) - ($betStats['total_win'] ?? 0);
+            
+            // 获取免费游戏购买次数(假设action_type中某个值代表免费游戏)
+            $freeGameCount = Db::connect('fortue_tiger')
+                ->name('game_bet_order')
+                ->where('app_id', $merchantId)
+                ->where('create_time', '>=', $dayStart)
+                ->where('create_time', '<=', $dayEnd)
+                ->where('action_type', 5) // 假设5代表免费游戏
+                ->count();
+            
+            // 获取平台费用(假设从转账记录表获取)
+            $platformFee = 0;
+            if (Db::connect('fortue_tiger')->query("SHOW TABLES LIKE 'tp_transfer_log'")) {
+                $platformFee = Db::connect('fortue_tiger')
+                    ->name('transfer_log')
+                    ->where('merchant_id', $merchantId)
+                    ->where('type', 'platform_fee')
+                    ->where('create_time', '>=', $dayStart)
+                    ->where('create_time', '<=', $dayEnd)
+                    ->sum('amount');
+            }
+            
+            $list[] = [
+                'date' => $date,
+                'merchant_id' => $merchantId,
+                'game_profit' => abs($betStats['game_profit'] ?? 0) / 100,  // 转换为元
+                'game_rtp' => $rtp,
+                'bet_amount' => ($betStats['bet_amount'] ?? 0) / 100,  // 转换为元
+                'bet_count' => $betStats['bet_count'] ?? 0,
+                'bet_users' => $betStats['bet_users'] ?? 0,
+                'register_users' => $registerUsers,
+                'login_users' => $loginUsers,
+                'commission_amount' => $commission / 100,  // 转换为元
+                'platform_fee' => $platformFee / 100,  // 转换为元
+                'free_game_count' => $freeGameCount,
+                'game_count' => $betStats['game_count'] ?? 0
+            ];
+        }
+        
+        return [
+            'list' => $list,
+            'total' => count($dates),
+            'page' => $page,
+            'limit' => $limit
+        ];
+    }
+    
+    /**
+     * 获取商户汇总统计
+     */
+    public static function getMerchantSummary($merchantId, $startDate, $endDate)
+    {
+        $startTime = strtotime($startDate . ' 00:00:00');
+        $endTime = strtotime($endDate . ' 23:59:59');
+        
+        // 获取汇总统计数据
+        $summary = Db::connect('fortue_tiger')
+            ->name('game_bet_order')
+            ->where('app_id', $merchantId)
+            ->where('create_time', '>=', $startTime)
+            ->where('create_time', '<=', $endTime)
+            ->where('status', 1)
+            ->field([
+                'COUNT(DISTINCT uname) as total_bet_users',
+                'COUNT(id) as total_bet_count',
+                'SUM(bet) as total_bet_amount',
+                'SUM(amount) as total_game_profit',
+                'SUM(total_win_amount) as total_win_amount',
+                'COUNT(DISTINCT game_id) as total_games',
+                'COUNT(DISTINCT DATE_FORMAT(FROM_UNIXTIME(create_time), "%Y-%m-%d")) as active_days'
+            ])
+            ->find();
+        
+        // 计算平均RTP
+        $avgRtp = 0;
+        if ($summary['total_bet_amount'] > 0) {
+            $avgRtp = round(($summary['total_win_amount'] / $summary['total_bet_amount']) * 100, 2);
+        }
+        
+        // 获取总注册用户
+        $totalRegisterUsers = Db::connect('fortue_tiger')
+            ->name('merchants_user')
+            ->where('app_id', $merchantId)
+            ->where('create_time', '>=', $startTime)
+            ->where('create_time', '<=', $endTime)
+            ->count();
+        
+        // 获取总登录用户
+        $totalLoginUsers = Db::connect('fortue_tiger')
+            ->name('merchants_user')
+            ->where('app_id', $merchantId)
+            ->where('login_time', '>=', $startTime)
+            ->where('login_time', '<=', $endTime)
+            ->count();
+        
+        return [
+            'total_bet_users' => $summary['total_bet_users'] ?? 0,
+            'total_bet_count' => $summary['total_bet_count'] ?? 0,
+            'total_bet_amount' => ($summary['total_bet_amount'] ?? 0) / 100,
+            'total_game_profit' => abs($summary['total_game_profit'] ?? 0) / 100,
+            'total_win_amount' => ($summary['total_win_amount'] ?? 0) / 100,
+            'avg_rtp' => $avgRtp,
+            'total_games' => $summary['total_games'] ?? 0,
+            'active_days' => $summary['active_days'] ?? 0,
+            'total_register_users' => $totalRegisterUsers,
+            'total_login_users' => $totalLoginUsers,
+            'total_commission' => (($summary['total_bet_amount'] ?? 0) - ($summary['total_win_amount'] ?? 0)) / 100
+        ];
+    }
+}

+ 241 - 0
app/model/MerchantHistoryModel.php

@@ -0,0 +1,241 @@
+<?php
+declare (strict_types = 1);
+
+namespace app\model;
+
+use think\Model;
+use think\facade\Db;
+
+/**
+ * 商户历史数据统计模型 - 基于tp_game_bet_order表统计所有历史数据
+ */
+class MerchantHistoryModel extends Model
+{
+    // 连接到fortue_tiger数据库
+    protected $connection = 'fortue_tiger';
+    
+    /**
+     * 获取商户历史数据统计
+     * @param int $merchantId 商户ID
+     * @param array $filters 过滤条件
+     */
+    public static function getMerchantHistoryStatistics($merchantId, $filters = [])
+    {
+        // 基础查询条件
+        $where = [
+            ['app_id', '=', $merchantId],
+            ['status', '=', 1]  // 只统计有效订单
+        ];
+        
+        // 日期范围过滤
+        if (!empty($filters['start_date'])) {
+            $startTime = strtotime($filters['start_date'] . ' 00:00:00');
+            $where[] = ['create_time', '>=', $startTime];
+        }
+        
+        if (!empty($filters['end_date'])) {
+            $endTime = strtotime($filters['end_date'] . ' 23:59:59');
+            $where[] = ['create_time', '<=', $endTime];
+        }
+        
+        // 获取汇总统计数据
+        $stats = Db::connect('fortue_tiger')
+            ->name('game_bet_order')
+            ->where($where)
+            ->field([
+                'COUNT(id) as total_orders',  // 注单数
+                'SUM(bet) as total_bet',  // 注单金额(分)
+                'SUM(amount) as total_profit',  // 游戏输赢(金额变化)
+                'SUM(total_win_amount) as total_win',  // 总赢得金额
+                'COUNT(DISTINCT uname) as bet_users',  // 投注用户数
+                'COUNT(DISTINCT CASE WHEN action_type = 5 THEN id END) as free_game_count'  // 购买免费游戏次数
+            ])
+            ->find();
+        
+        // 计算RTP(Return to Player)
+        $rtp = 0;
+        if ($stats['total_bet'] > 0) {
+            // RTP = (返还给玩家的金额 / 投注总额) * 100
+            $rtp = round(($stats['total_win'] / $stats['total_bet']) * 100, 2);
+        }
+        
+        // 获取注册用户数(根据时间范围)
+        $registerQuery = Db::connect('fortue_tiger')
+            ->name('merchants_user')
+            ->where('app_id', $merchantId);
+            
+        if (!empty($filters['start_date'])) {
+            $registerQuery->where('create_time', '>=', strtotime($filters['start_date'] . ' 00:00:00'));
+        }
+        
+        if (!empty($filters['end_date'])) {
+            $registerQuery->where('create_time', '<=', strtotime($filters['end_date'] . ' 23:59:59'));
+        }
+        
+        $registerUsers = $registerQuery->count();
+        
+        // 获取登录用户数(根据时间范围)
+        $loginQuery = Db::connect('fortue_tiger')
+            ->name('merchants_user')
+            ->where('app_id', $merchantId);
+            
+        if (!empty($filters['start_date'])) {
+            $loginQuery->where('login_time', '>=', strtotime($filters['start_date'] . ' 00:00:00'));
+        }
+        
+        if (!empty($filters['end_date'])) {
+            $loginQuery->where('login_time', '<=', strtotime($filters['end_date'] . ' 23:59:59'));
+        }
+        
+        $loginUsers = $loginQuery->where('login_time', '>', 0)->count();
+        
+        // 假设汇率(可以从配置或其他表获取)
+        $thbToUsdtRate = 0.028;  // 1 THB = 0.028 USDT (示例汇率)
+        
+        // 计算抽水额度(平台盈利 = 下注金额 - 赢得金额)
+        $commission = ($stats['total_bet'] ?? 0) - ($stats['total_win'] ?? 0);
+        
+        // 组装返回数据
+        $result = [
+            'rtp' => $rtp . '%',  // RTP百分比
+            'total_orders' => number_format($stats['total_orders'] ?? 0),  // 注单数
+            'total_bet_thb' => number_format(($stats['total_bet'] ?? 0) / 100, 2) . ' THB',  // 注单金额(THB)
+            'game_profit_thb' => number_format(abs($stats['total_profit'] ?? 0) / 100, 2) . ' THB',  // 游戏输赢(THB)
+            'total_bet_usdt' => number_format(($stats['total_bet'] ?? 0) / 100 * $thbToUsdtRate, 4) . ' USDT',  // 注单金额(USDT)
+            'game_profit_usdt' => number_format(abs($stats['total_profit'] ?? 0) / 100 * $thbToUsdtRate, 4) . ' USDT',  // 游戏输赢(USDT)
+            'login_users' => $loginUsers,  // 登录用户
+            'register_users' => $registerUsers,  // 注册用户
+            'bet_users' => $stats['bet_users'] ?? 0,  // 投注用户
+            'commission_usdt' => number_format($commission / 100 * $thbToUsdtRate, 4) . ' USDT',  // 抽水额度(USDT)
+            'free_game_count' => $stats['free_game_count'] ?? 0,  // 购买免费游戏次数
+            
+            // 原始数据(不带格式化)
+            'raw_data' => [
+                'rtp' => $rtp,
+                'total_orders' => $stats['total_orders'] ?? 0,
+                'total_bet' => ($stats['total_bet'] ?? 0) / 100,
+                'game_profit' => abs($stats['total_profit'] ?? 0) / 100,
+                'total_win' => ($stats['total_win'] ?? 0) / 100,
+                'commission' => $commission / 100,
+                'thb_to_usdt_rate' => $thbToUsdtRate
+            ]
+        ];
+        
+        return $result;
+    }
+    
+    /**
+     * 获取商户历史数据列表(按月份或按天统计)
+     */
+    public static function getMerchantHistoryList($merchantId, $groupBy = 'month', $page = 1, $limit = 10, $filters = [])
+    {
+        // 日期格式
+        $dateFormat = $groupBy === 'month' ? '%Y-%m' : '%Y-%m-%d';
+        
+        // 基础SQL
+        $sql = "SELECT 
+                    DATE_FORMAT(FROM_UNIXTIME(create_time), '{$dateFormat}') as period,
+                    COUNT(id) as total_orders,
+                    SUM(bet) as total_bet,
+                    SUM(amount) as game_profit,
+                    SUM(total_win_amount) as total_win,
+                    COUNT(DISTINCT uname) as bet_users,
+                    COUNT(DISTINCT CASE WHEN action_type = 5 THEN id END) as free_game_count
+                FROM tp_game_bet_order
+                WHERE app_id = ? AND status = 1";
+        
+        $params = [$merchantId];
+        
+        // 日期范围
+        if (!empty($filters['start_date'])) {
+            $sql .= " AND create_time >= ?";
+            $params[] = strtotime($filters['start_date'] . ' 00:00:00');
+        }
+        
+        if (!empty($filters['end_date'])) {
+            $sql .= " AND create_time <= ?";
+            $params[] = strtotime($filters['end_date'] . ' 23:59:59');
+        }
+        
+        $sql .= " GROUP BY period ORDER BY period DESC";
+        
+        // 获取总数
+        $countSql = "SELECT COUNT(DISTINCT DATE_FORMAT(FROM_UNIXTIME(create_time), '{$dateFormat}')) as total
+                     FROM tp_game_bet_order
+                     WHERE app_id = ? AND status = 1";
+        
+        $countParams = [$merchantId];
+        if (!empty($filters['start_date'])) {
+            $countSql .= " AND create_time >= ?";
+            $countParams[] = strtotime($filters['start_date'] . ' 00:00:00');
+        }
+        if (!empty($filters['end_date'])) {
+            $countSql .= " AND create_time <= ?";
+            $countParams[] = strtotime($filters['end_date'] . ' 23:59:59');
+        }
+        
+        $total = Db::connect('fortue_tiger')->query($countSql, $countParams)[0]['total'] ?? 0;
+        
+        // 分页
+        $sql .= " LIMIT " . (($page - 1) * $limit) . ", " . $limit;
+        
+        $list = Db::connect('fortue_tiger')->query($sql, $params);
+        
+        // 假设汇率
+        $thbToUsdtRate = 0.028;
+        
+        // 处理每条记录
+        foreach ($list as &$item) {
+            // 计算RTP
+            $item['rtp'] = 0;
+            if ($item['total_bet'] > 0) {
+                $item['rtp'] = round(($item['total_win'] / $item['total_bet']) * 100, 2);
+            }
+            
+            // 获取该时期的注册和登录用户
+            if ($groupBy === 'month') {
+                $periodStart = strtotime($item['period'] . '-01 00:00:00');
+                $periodEnd = strtotime(date('Y-m-t', $periodStart) . ' 23:59:59');
+            } else {
+                $periodStart = strtotime($item['period'] . ' 00:00:00');
+                $periodEnd = strtotime($item['period'] . ' 23:59:59');
+            }
+            
+            $item['register_users'] = Db::connect('fortue_tiger')
+                ->name('merchants_user')
+                ->where('app_id', $merchantId)
+                ->where('create_time', '>=', $periodStart)
+                ->where('create_time', '<=', $periodEnd)
+                ->count();
+            
+            $item['login_users'] = Db::connect('fortue_tiger')
+                ->name('merchants_user')
+                ->where('app_id', $merchantId)
+                ->where('login_time', '>=', $periodStart)
+                ->where('login_time', '<=', $periodEnd)
+                ->count();
+            
+            // 计算抽水
+            $commission = ($item['total_bet'] - $item['total_win']);
+            
+            // 格式化数据
+            $item['commission_usdt'] = $commission / 100 * $thbToUsdtRate;
+            $item['total_bet_thb'] = $item['total_bet'] / 100;
+            $item['total_bet_usdt'] = $item['total_bet'] / 100 * $thbToUsdtRate;
+            $item['game_profit_thb'] = abs($item['game_profit']) / 100;
+            $item['game_profit_usdt'] = abs($item['game_profit']) / 100 * $thbToUsdtRate;
+            
+            // 移除原始字段
+            unset($item['total_bet']);
+            unset($item['game_profit']);
+            unset($item['total_win']);
+        }
+        
+        return [
+            'list' => $list,
+            'total' => $total,
+            'page' => $page,
+            'limit' => $limit
+        ];
+    }
+}

+ 19 - 0
route/app.php

@@ -103,3 +103,22 @@ Route::group('transfer_log', function () {
     Route::get('statistics', 'TransferLog/statistics');
     Route::get('export', 'TransferLog/export');
 })->middleware([\app\middleware\AuthMiddleware::class, \app\middleware\BehaviorLogMiddleware::class]);
+
+// 每日数据统计相关路由
+Route::group('daily_statistics', function () {
+    // 商户每日数据
+    Route::get('merchant_daily_list', 'DailyStatistics/merchantDailyList');
+    Route::get('merchant_summary', 'DailyStatistics/merchantSummary');
+    Route::get('export_merchant_daily', 'DailyStatistics/exportMerchantDaily');
+    
+    // 商户历史数据
+    Route::get('merchant_history', 'DailyStatistics/merchantHistory');
+    Route::get('merchant_history_list', 'DailyStatistics/merchantHistoryList');
+    Route::get('export_merchant_history', 'DailyStatistics/exportMerchantHistory');
+    
+    // 游戏每日数据
+    Route::get('game_daily_list', 'DailyStatistics/gameDailyList');
+    Route::get('game_summary', 'DailyStatistics/gameSummary');
+    Route::get('game_list', 'DailyStatistics/getGameList');
+    Route::get('export_game_daily', 'DailyStatistics/exportGameDaily');
+})->middleware([\app\middleware\AuthMiddleware::class, \app\middleware\BehaviorLogMiddleware::class]);