diff --git a/Application/Admin/Controller/ExportController.class.php b/Application/Admin/Controller/ExportController.class.php index 6929e92b7..5f0c055e9 100644 --- a/Application/Admin/Controller/ExportController.class.php +++ b/Application/Admin/Controller/ExportController.class.php @@ -4,6 +4,7 @@ namespace Admin\Controller; use Think\Controller; use GuzzleHttp\Client; use Admin\Model\PromoteModel; +use Base\Repository\UserRepository; use Base\Tool\AggregateClient; class ExportController extends Controller @@ -4193,8 +4194,10 @@ class ExportController extends Controller } $gameName = $deviceType ? get_game_name($searchGameId) : $baseGame['name']; $promoteName = '全部'; + $promote = null; if ($promoteId) { - $promoteName = get_promote_account($promoteId); + $promote = M('promote', 'tab_')->where(['id' => $promoteId])->find(); + $promoteName = $promote['account']; } $data = $result['data']['records']; $dayList = [1, 2, 3, 4, 5, 6, 7, 15, 30]; @@ -4210,6 +4213,18 @@ class ExportController extends Controller } $data[$key] = $item; } + + $repository = new UserRepository(); + $deviceKey = 0; + if ($deviceType) { + $deviceKey = $deviceType == 'android' ? 1 : 2; + } + $otherResult = $repository->getUserRetention($baseGameId, [$start, $end], $deviceKey, $promote, [60, 90]); + foreach ($data as $key => $item) { + $otherItem = $otherResult[$item['date']]; + $data[$key]['retention_day60'] = $otherItem['retention_rate'][60]; + $data[$key]['retention_day90'] = $otherItem['retention_rate'][90]; + } } else { $this->error($error); } diff --git a/Application/Admin/Controller/StatController.class.php b/Application/Admin/Controller/StatController.class.php index f63b9f943..bdde203d9 100644 --- a/Application/Admin/Controller/StatController.class.php +++ b/Application/Admin/Controller/StatController.class.php @@ -4,6 +4,7 @@ namespace Admin\Controller; use Admin\Model\SpendModel; use Open\Model\UserLoginRecordModel; use Admin\Model\UserPlayModel; +use Base\Repository\UserRepository; use User\Api\UserApi as UserApi; use GuzzleHttp\Client; @@ -208,8 +209,10 @@ class StatController extends ThinkController $dayList = [1, 2, 3, 4, 5, 6, 7, 15, 30]; $gameName = $deviceType ? get_game_name($searchGameId) : $baseGame['name']; $promoteName = '全部'; + $promote = null; if ($promoteId) { - $promoteName = get_promote_account($promoteId); + $promote = M('promote', 'tab_')->where(['id' => $promoteId])->find(); + $promoteName = $promote['account']; } foreach ($data as $key => $item) { $item['promote_name'] = $promoteName; @@ -223,6 +226,18 @@ class StatController extends ThinkController } $data[$key] = $item; } + + $repository = new UserRepository(); + $deviceKey = 0; + if ($deviceType) { + $deviceKey = $deviceType == 'android' ? 1 : 2; + } + $otherResult = $repository->getUserRetention($baseGameId, [$start, $end], $deviceKey, $promote, [60, 90]); + foreach ($data as $key => $item) { + $otherItem = $otherResult[$item['date']]; + $data[$key]['retention_day60'] = $otherItem['retention_rate'][60]; + $data[$key]['retention_day90'] = $otherItem['retention_rate'][90]; + } if ($dataOrder) { $data = $this->multisort($data, $orderColumn, $orderType); } diff --git a/Application/Admin/View/Stat/userretention.html b/Application/Admin/View/Stat/userretention.html index fabef79ec..50004a3fa 100644 --- a/Application/Admin/View/Stat/userretention.html +++ b/Application/Admin/View/Stat/userretention.html @@ -108,6 +108,10 @@ 15日留存 30日留存 + + 60日留存 + + 90日留存 @@ -135,6 +139,8 @@ {$vo['retention_day7']}% {$vo['retention_day15']}% {$vo['retention_day30']}% + {$vo['retention_day60']}% + {$vo['retention_day90']}% -- -- @@ -145,6 +151,8 @@ -- -- -- + -- + -- diff --git a/Application/Base/Repository/GameRepository.class.php b/Application/Base/Repository/GameRepository.class.php index 3e358037e..d05539c13 100644 --- a/Application/Base/Repository/GameRepository.class.php +++ b/Application/Base/Repository/GameRepository.class.php @@ -2,6 +2,7 @@ namespace Base\Repository; +use Base\Service\PromoteService; use Base\Tool\Registry; class GameRepository @@ -68,7 +69,7 @@ class GameRepository return $gameIds; } - public function getUserRegisterCount($baseGame, $date, $deviceType = 0) + public function getUserRegisterCount($baseGame, $date, $deviceType = 0, $promote = null) { $gameIds = $this->getGameIdsByBaseGame($baseGame, $deviceType); $timeBegin = strtotime($date . ' 00:00:00'); @@ -76,17 +77,25 @@ class GameRepository $subCondition = [ 'game_id' => ['in', $gameIds], - '_string' => 'tab_user.id=tab_user_play_info.user_id' + '_string' => 'tab_user_play.user_id=tab_user_play_info.user_id' ]; $subSql = M('user_play_info', 'tab_')->field('1')->where($subCondition)->select(false); - return M('user', 'tab_')->where([ - 'register_time' => ['between', [$timeBegin, $timeEnd]], - '_string' => 'exists (' . $subSql . ')' + $sqlStr = 'exists (' . $subSql . ')'; + + if ($promote) { + $promoteService = new PromoteService(); + $sqlStr .= ' and promote_id in (' . $promoteService->subInSql($promote) . ')'; + } + + return M('user_play', 'tab_')->where([ + // 'register_time' => ['between', [$timeBegin, $timeEnd]], + 'create_time' => ['between', [$timeBegin, $timeEnd]], + '_string' => $sqlStr ])->count(); } - public function getUserRetentionCount($baseGame, $date, $day, $deviceType = 0) + public function getUserRetentionCount($baseGame, $date, $day, $deviceType = 0, $promote = null) { $gameIds = $this->getGameIdsByBaseGame($baseGame, $deviceType); @@ -96,14 +105,21 @@ class GameRepository $subCondition = [ 'game_id' => ['in', $gameIds], - '_string' => 'tab_user.id=tab_user_play_info.user_id', + '_string' => 'tab_user_play.user_id=tab_user_play_info.user_id', 'play_time' => ['egt', $retentionTime], ]; $subSql = M('user_play_info', 'tab_')->field('1')->where($subCondition)->select(false); - return M('user', 'tab_')->where([ - 'register_time' => ['between', [$timeBegin, $timeEnd]], - '_string' => 'exists (' . $subSql . ')' + $sqlStr = 'exists (' . $subSql . ')'; + if ($promote) { + $promoteService = new PromoteService(); + $sqlStr .= ' and promote_id in (' . $promoteService->subInSql($promote) . ')'; + } + + return M('user_play', 'tab_')->where([ + // 'register_time' => ['between', [$timeBegin, $timeEnd]], + 'create_time' => ['between', [$timeBegin, $timeEnd]], + '_string' => $sqlStr ])->count(); } } \ No newline at end of file diff --git a/Application/Base/Repository/UserRepository.class.php b/Application/Base/Repository/UserRepository.class.php index 1d85ae130..a46ca6446 100644 --- a/Application/Base/Repository/UserRepository.class.php +++ b/Application/Base/Repository/UserRepository.class.php @@ -565,4 +565,35 @@ class UserRepository ->find(); return $item['count']; } + + public function getUserRetention($baseGameId, $dateRange, $deviceType, $promote = null, $dayList = [60, 90]) + { + $begin = $dateRange[0]; + $end = $dateRange[1]; + + $repository = new GameRepository(); + $baseGame = M('base_game', 'tab_')->where(['id' => $baseGameId])->find(); + + $beginDate = strtotime($begin); + $endDate = strtotime($end); + $dayTime = 24 * 3600; + + $records = []; + for ($date = $beginDate; $date <= $endDate; $date = $date + $dayTime) { + $dateStr = date('Y-m-d', $date); + $userRegisterCount = $repository->getUserRegisterCount($baseGame, $dateStr, $deviceType, $promote); + + $retentionRates = []; + foreach ($dayList as $day) { + $retentionCount = $repository->getUserRetentionCount($baseGame, $dateStr, $day, $deviceType, $promote); + $retentionRates[$day] = $userRegisterCount == 0 ? '--' : round($retentionCount / $userRegisterCount * 100, 2); + } + $records[$dateStr] = [ + 'date' => $dateStr, + 'register_count' => $userRegisterCount, + 'retention_rate' => $retentionRates, + ]; + } + return $records; + } } \ No newline at end of file