2 Commits d5dc1e7630 ... f63797c99c

Autor SHA1 Mensagem Data
  aiden f63797c99c Merge branch 'main' of s.long.bid:liu/merchant_admin 3 meses atrás
  aiden ef7eb92771 update:增加概览数据接口 3 meses atrás

+ 1 - 0
.serena/.gitignore

@@ -0,0 +1 @@
+/cache

+ 68 - 0
.serena/project.yml

@@ -0,0 +1,68 @@
+# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby)
+#  * For C, use cpp
+#  * For JavaScript, use typescript
+# Special requirements:
+#  * csharp: Requires the presence of a .sln file in the project folder.
+language: php
+
+# whether to use the project's gitignore file to ignore files
+# Added on 2025-04-07
+ignore_all_files_in_gitignore: true
+# list of additional paths to ignore
+# same syntax as gitignore, so you can use * and **
+# Was previously called `ignored_dirs`, please update your config if you are using that.
+# Added (renamed) on 2025-04-07
+ignored_paths: []
+
+# whether the project is in read-only mode
+# If set to true, all editing tools will be disabled and attempts to use them will result in an error
+# Added on 2025-04-18
+read_only: false
+
+
+# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
+# Below is the complete list of tools for convenience.
+# To make sure you have the latest list of tools, and to view their descriptions, 
+# execute `uv run scripts/print_tool_overview.py`.
+#
+#  * `activate_project`: Activates a project by name.
+#  * `check_onboarding_performed`: Checks whether project onboarding was already performed.
+#  * `create_text_file`: Creates/overwrites a file in the project directory.
+#  * `delete_lines`: Deletes a range of lines within a file.
+#  * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
+#  * `execute_shell_command`: Executes a shell command.
+#  * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
+#  * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
+#  * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
+#  * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
+#  * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
+#  * `initial_instructions`: Gets the initial instructions for the current project.
+#     Should only be used in settings where the system prompt cannot be set,
+#     e.g. in clients you have no control over, like Claude Desktop.
+#  * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
+#  * `insert_at_line`: Inserts content at a given line in a file.
+#  * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
+#  * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
+#  * `list_memories`: Lists memories in Serena's project-specific memory store.
+#  * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
+#  * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
+#  * `read_file`: Reads a file within the project directory.
+#  * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
+#  * `remove_project`: Removes a project from the Serena configuration.
+#  * `replace_lines`: Replaces a range of lines within a file with new content.
+#  * `replace_symbol_body`: Replaces the full definition of a symbol.
+#  * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
+#  * `search_for_pattern`: Performs a search for a pattern in the project.
+#  * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
+#  * `switch_modes`: Activates modes by providing a list of their names
+#  * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
+#  * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
+#  * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
+#  * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
+excluded_tools: []
+
+# initial prompt for the project. It will always be given to the LLM upon activating the project
+# (contrary to the memories, which are loaded on demand).
+initial_prompt: ""
+
+project_name: "merchant_admin"

+ 0 - 18
app/controller/Index.php

@@ -1,18 +0,0 @@
-<?php
-
-namespace app\controller;
-
-use app\BaseController;
-
-class Index extends BaseController
-{
-    public function index()
-    {
-        return '<style>*{ padding: 0; margin: 0; }</style><iframe src="https://www.thinkphp.cn/welcome?version=' . \think\facade\App::version() . '" width="100%" height="100%" frameborder="0" scrolling="auto"></iframe>';
-    }
-
-    public function hello($name = 'ThinkPHP8')
-    {
-        return 'hello,' . $name;
-    }
-}

+ 118 - 0
app/controller/Overview.php

@@ -0,0 +1,118 @@
+<?php
+
+namespace app\controller;
+
+use app\BaseController;
+use app\model\MerchantStatisModel;
+use app\model\UserBehaviorLogModel;
+use app\common\CommonUtils;
+use app\model\GameBetGameModel;
+use app\model\MerchantsUserModel;
+use think\facade\Request;
+
+class Overview extends BaseController
+{
+    /**
+     * 仪表盘 - 获取概览统计数据
+     */
+    public function Dashboard()
+    {
+        $userInfo = $this->getUserInfo();
+        
+        try {
+            // 获取昨、今日时间范围
+            $today = date('Y-m-d');
+            $filtter = [
+                'start_time' => date('Y-m-d', strtotime($today) - 86400),
+                'end_time' => date('Y-m-d', strtotime($today) + 86400),
+            ];       
+            $merchantId = $userInfo['merchant_id'];
+            
+            // 获取昨、今日游戏相关统计
+            $dailySummary = GameBetGameModel::getGameDailySummary($merchantId, $filtter);
+            // 获取玩家统计数据
+            $playerSummary = MerchantsUserModel::getPlayerStatistics($merchantId, $filtter);
+            $tempPlayerData = [];
+            if ($playerSummary) {
+                foreach ($playerSummary as $row) {
+                    $date = $row['date'] == $today ? 'today' : 'yesterday';
+                    $tempPlayerData[$date] = $row;
+                }                
+            }
+
+            if ($dailySummary) {
+                foreach ($dailySummary as $row) {
+
+                    $date = $row['date'] == $today ? 'today' : 'yesterday';
+                    $row['commission'] = CommonUtils::convertBalance($row['game_profit'] * 0.08, false);
+                    $row['bet_amount'] = CommonUtils::convertBalance($row['bet_amount'], false);
+                    $row['game_profit'] = CommonUtils::convertBalance($row['game_profit'], false);
+                    $row['register_users'] = $tempPlayerData[$date]['register_users'] ?? 0;
+                    $row['login_users'] = $tempPlayerData[$date]['login_users'] ?? 0;
+                    $row['online_users'] = 0;
+                    $dashboardData[$date] = $row;
+                }
+            }
+                      
+            // 在线人数、登录数据
+            $dashboardData['online_data'] = [];
+            $dashboardData['login_data'] = [];
+
+            return json(['code' => 0, 'msg' => 'success', 'data' => $dashboardData]);
+            
+        } catch (\Exception $e) {
+            return json(['code' => -1, 'msg' => '获取仪表盘数据失败: ' . $e->getMessage()]);
+        }
+    }
+
+    /**
+     * 结算报表 - 按日期查询投注数据
+     */
+    public function SettlementReport() 
+    {
+        $userInfo = $this->request->userInfo;
+        
+        // 获取查询参数
+        $page = Request::get('page', 1, 'intval');
+        $limit = Request::get('limit', 10, 'intval');
+
+        // 筛选条件
+        $filters = [
+            // 时间筛选
+            'start_time' => Request::get('start_time', date('Y-m-d', strtotime('-7 days')), 'trim'),
+            'end_time' => Request::get('end_time', date('Y-m-d'), 'trim'),
+        ];
+        
+        try {
+            // 获取商户每日数据
+            $result = MerchantStatisModel::getMerchantDailyList(
+                $userInfo['merchant_id'],
+                $page,
+                $limit,
+                $filters,                
+            );
+            
+            // 格式化数据
+            foreach ($result['list'] as &$item) {
+                $item['game_profit'] = CommonUtils::convertBalance($item['game_profit'], false);
+                $item['game_profit_usdt'] = $item['game_profit'];
+                $item['bet_amount'] = CommonUtils::convertBalance($item['bet_amount'], false);
+                $item['bet_amount_usdt'] = $item['bet_amount'];
+                $item['platform_fee'] = CommonUtils::convertBalance($item['bet_amount'] * 0.08, false);
+                $item['platform_fee_usdt'] = $item['platform_fee'];
+                $item['region'] = '';
+            }
+            
+            return json_success($result, '获取成功');
+        } catch (\Exception $e) {
+            return json_error([], '获取商户每日数据失败:' . $e->getMessage());
+        }
+    }
+
+    /**
+     * 导出结算报表
+     */
+    public function exportSettlement() {
+        ;
+    }
+}

+ 40 - 0
app/model/GameBetGameModel.php

@@ -299,4 +299,44 @@ class GameBetGameModel extends Model
             'limit' => $limit
         ];
     }
+
+    /**
+     * 获取游戏每日数据
+     */
+    public static function getGameDailySummary($merchantId, $filters = [])
+    {
+        $where = [
+            ['app_id', '=', $merchantId]
+        ];
+        
+        // 时间筛选
+        if (!empty($filters['start_time'])) {
+            $startTime = strtotime($filters['start_time']);
+            $where[] = ['create_time', '>=', $startTime];
+        }
+        
+        if (!empty($filters['end_time'])) {
+            $endTime = strtotime($filters['end_time']);
+            $where[] = ['create_time', '<=', $endTime];
+        }
+
+        if (!empty($filters['game_id'])) {
+            $gameId = is_array($filters['game_id']) ? $filters['game_id'] : explode(',', $filters['game_id']);
+            $where[] = ['game_id', 'in', $gameId];
+        }
+
+        $list = self::field([
+                "FROM_UNIXTIME(create_time, '%Y-%m-%d') as date", // 日期
+                'COUNT(DISTINCT uname) as bet_users',  // 投注用户数
+                'COUNT(id) as bet_count',  // 注单数
+                'SUM(bet) as bet_amount',  // 注单金额(下注分数)
+                'SUM(total_win_amount) as game_profit',  // 游戏输赢(金额变化)
+        ])
+        ->where($where)
+        ->group('date')
+        ->select()
+        ->toArray();
+
+        return $list;
+    }    
 }

+ 9 - 1
route/app.php

@@ -151,7 +151,7 @@ Route::group('trend_statis', function () {
     Route::get('merchant_daily', 'TrendStatis/MerchantDaily');
 })->middleware([\app\middleware\AuthMiddleware::class, \app\middleware\BehaviorLogMiddleware::class]);
 
-// 排榜相关路由
+// 排榜相关路由
 Route::group('rank_list', function () {
     // 赢钱榜
     Route::get('win_amount', 'RankList/WinAmount');
@@ -160,3 +160,11 @@ Route::group('rank_list', function () {
     // 注单额榜
     Route::get('bet_amount', 'RankList/BetAmount');
 })->middleware([\app\middleware\AuthMiddleware::class, \app\middleware\BehaviorLogMiddleware::class]);
+
+// 概览相关路由
+Route::group('overview', function () {
+    // 仪表盘
+    Route::get('dashboard', 'Overview/Dashboard');
+    // 输钱榜
+    Route::get('settlement_report', 'Overview/SettlementReport');
+})->middleware([\app\middleware\AuthMiddleware::class, \app\middleware\BehaviorLogMiddleware::class]);