AnalyseLogic.php 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. <?php
  2. // 玩家日志逻
  3. namespace app\v1\logic\gameLog;
  4. use app\v1\logic\tool\ToolLogic;
  5. use plugin\saiadmin\basic\BaseLogic;
  6. use plugin\saiadmin\exception\ApiException;
  7. use support\think\Db;
  8. class AnalyseLogic extends BaseLogic
  9. {
  10. // 注册按日
  11. public function getRegDayDataList($where){
  12. $params = $this->searchByAuth($where);
  13. $whereSql = $this->generateWhereSql($params);
  14. $field = "SUM(reg_total) AS reg_total, tdate,game_id";
  15. $baseData = $this->generateYearUnionList('base_total_day_',$where['reg_date'],$whereSql,$field,'game_id,tdate');
  16. $data=[];
  17. foreach($baseData as $row){
  18. $tdate = $row['tdate'];
  19. $game_id = $row['game_id'];
  20. $data[$game_id][$tdate] = $row['reg_total'];
  21. $data[$game_id]['total'] = !empty($data[$game_id]['total']) ? $data[$game_id]['total'] + $row['reg_total'] : $row['reg_total'];
  22. $data[$game_id]['game_id'] = $game_id;
  23. }
  24. $list = array_values($data);
  25. $totalRow = ['game_id'=>'合计'];
  26. foreach($list as &$row){
  27. $totalRow['total'] = !empty($totalRow['total']) ? $totalRow['total'] + $row['total'] : $row['total'];
  28. foreach ($row as $key => $value) {
  29. if($key == 'total' || $key == 'game_id'){
  30. continue;
  31. }
  32. $totalRow[$key] = !empty($totalRow[$key]) ? $totalRow[$key] + $value : $value;
  33. }
  34. }
  35. // 获取两个注册日期之间的日期列表
  36. $dateList = ToolLogic::getDatesBetween($where['reg_date'][0],$where['reg_date'][1]);
  37. $columnsData = [
  38. [
  39. 'title' => '游戏ID',
  40. 'dataIndex' => 'game_id',
  41. 'width' => 120,
  42. ],
  43. [
  44. 'title' => '游戏',
  45. 'dataIndex' => 'game_name',
  46. 'width' => 120,
  47. ],
  48. [
  49. 'title' => '合计',
  50. 'dataIndex' => 'total',
  51. 'width' => 120,
  52. ]
  53. ];
  54. foreach($dateList as $date){
  55. $columnsData[] = [
  56. 'title' => $date,
  57. 'dataIndex' => $date,
  58. 'width' => 120,
  59. ];
  60. }
  61. $result['data'] = $list;
  62. $result['totalRow'] = $totalRow;
  63. $result['columns'] = $columnsData;
  64. return $result;
  65. }
  66. // 注册按时
  67. public function getRegHourDataList($where){
  68. $params = $this->searchByAuth($where);
  69. $field = "SUM(role_create_user) AS role_create_user, tdate,game_id,thour";
  70. $regDate = $where['reg_date'];
  71. // 将$regDate转化为年月格式,如202509
  72. $ym = date('Ym', strtotime($regDate));
  73. $tableName = 'base_total_hour_'.$ym;
  74. $whereSql = 'WHERE 1=1';
  75. if(!empty($params['game_id'])){
  76. $whereSql .= " AND game_id IN(" . implode(',', $params['game_id']) . ")";
  77. }
  78. if(!empty($params['reg_date'])){
  79. $whereSql .= " AND tdate = '" .$params['reg_date']. "'";
  80. }
  81. $sql = "SELECT {$field} FROM {$tableName} {$whereSql} GROUP BY game_id,thour,tdate";
  82. $baseData = Db::connect('db_data_report')->query($sql);
  83. $data = [];
  84. foreach($baseData as &$row){
  85. $game_id = $row['game_id'];
  86. $thour = $row['thour'];
  87. $data[$game_id]['h'.$thour] = $row['role_create_user'];
  88. $data[$game_id]['total'] = !empty($data[$game_id]['total']) ? $data[$game_id]['total'] + $row['role_create_user'] : $row['role_create_user'];
  89. $data[$game_id]['game_id'] = $game_id;
  90. }
  91. $list = array_values($data);
  92. $totalRow = ['game_id'=>'合计'];
  93. foreach($list as &$row){
  94. $totalRow['total'] = !empty($totalRow['total']) ? $totalRow['total'] + $row['total'] : $row['total'];
  95. foreach ($row as $key => $value) {
  96. if($key == 'total' || $key == 'game_id'){
  97. continue;
  98. }
  99. $totalRow[$key] = !empty($totalRow[$key]) ? $totalRow[$key] + $value : $value;
  100. }
  101. }
  102. $result['data'] = $list;
  103. $result['totalRow'] = $totalRow;
  104. return $result;
  105. }
  106. // 留存按日
  107. public function getRetentionDayDataList($where){
  108. $params = $this->searchByAuth($where);
  109. // 构建whereSql
  110. $whereSql = '';
  111. if(!empty($params['game_id'])){
  112. $whereSql .= " AND game_id IN(" . implode(',', $params['game_id']) . ")";
  113. }
  114. if(!empty($params['reg_date'])){
  115. $whereSql .= " AND tdate BETWEEN '{$params['reg_date'][0]}' AND '{$params['reg_date'][1]}'";
  116. }
  117. $data = [];
  118. $totalRow = ['game_id'=>'合计'];
  119. $baseField = "SUM(reg_total) AS reg_total, tdate,game_id";
  120. $activeField = "SUM(active_total) AS active_total, reg_date,game_id,days";
  121. // 1. 查询每天的注册数,根据注册时间,游戏
  122. $baseData = $this->generateYearUnionList('base_total_day_',$params['reg_date'],$whereSql,$baseField,'game_id,tdate');
  123. $baseData = array_column($baseData,null,'tdate');
  124. // 2. 查询每天的活跃数,根据注册时间,游戏,留存天数
  125. $activeWhereSql = str_replace("AND tdate", "AND reg_date", $whereSql);
  126. if(!empty($params['days'])){
  127. $activeWhereSql .= " AND days = {$params['days']}";
  128. }
  129. $activeData = $this->generateYearUnionList('game_active_day_',$params['reg_date'],$activeWhereSql,$activeField,'game_id,reg_date');
  130. $activeData = array_column($activeData,null,'reg_date');
  131. foreach($baseData as $row){
  132. $game_id = $row['game_id'];
  133. $tdate = $row['tdate'];
  134. $data[$game_id]['game_id'] = $game_id;
  135. $data[$game_id][$tdate]['reg_total'] = $row['reg_total'];
  136. $data[$game_id][$tdate]['active_total'] = !empty($activeData[$tdate]['active_total']) ? $activeData[$tdate]['active_total'] : 0;
  137. $data[$game_id][$tdate]['retention_total'] = ToolLogic::getPercent($data[$game_id][$tdate]['active_total'],$data[$game_id][$tdate]['reg_total']);
  138. // 每日合计
  139. $data[$game_id]['total_reg_total'] = !empty($data[$game_id]['total_reg_total']) ? $data[$game_id]['total_reg_total'] + $data[$game_id][$tdate]['reg_total'] : $data[$game_id][$tdate]['reg_total'];
  140. $data[$game_id]['total_active_total'] = !empty($data[$game_id]['total_active_total']) ? $data[$game_id]['total_active_total'] + $data[$game_id][$tdate]['active_total'] : $data[$game_id][$tdate]['active_total'];
  141. // 底部合计
  142. $totalRow['total_reg_total'] = !empty($totalRow['total_reg_total']) ? $totalRow['total_reg_total'] + $data[$game_id][$tdate]['reg_total'] : $data[$game_id][$tdate]['reg_total'];
  143. $totalRow['total_active_total'] = !empty($totalRow['total_active_total']) ? $totalRow['total_active_total'] + $data[$game_id][$tdate]['active_total'] : $data[$game_id][$tdate]['active_total'];
  144. $totalRow[$tdate]['reg_total'] = !empty($totalRow[$tdate]['reg_total']) ? $totalRow[$tdate]['reg_total'] + $data[$game_id][$tdate]['reg_total'] : $data[$game_id][$tdate]['reg_total'];
  145. $totalRow[$tdate]['active_total'] = !empty($totalRow[$tdate]['active_total']) ? $totalRow[$tdate]['active_total'] + $data[$game_id][$tdate]['active_total'] : $data[$game_id][$tdate]['active_total'];
  146. }
  147. $data = array_values($data);
  148. foreach($data as &$row){
  149. foreach($row as $key => $value){
  150. if($key == 'total_reg_total' || $key == 'game_id'){
  151. continue;
  152. }
  153. if($key == 'total_active_total'){
  154. $row['total'] = ToolLogic::getPercent($row['total_active_total'],$row['total_reg_total']);
  155. }else{
  156. $row[$key] = ToolLogic::getPercent($value['active_total'],$value['reg_total']);
  157. }
  158. }
  159. }
  160. foreach($totalRow as $totalKey => &$row){
  161. if($totalKey == 'game_id' || $totalKey == 'total_active_total'||$totalKey == 'total_reg_total'){
  162. continue;
  163. }
  164. $totalRow[$totalKey] = ToolLogic::getPercent($row['active_total'],$row['reg_total']);
  165. }
  166. $totalRow['total'] = ToolLogic::getPercent($totalRow['total_active_total'],$totalRow['total_reg_total']);
  167. // 获取两个注册日期之间的日期列表
  168. $dateList = ToolLogic::getDatesBetween($where['reg_date'][0],$where['reg_date'][1]);
  169. $columnsData = [
  170. [
  171. 'title' => '游戏ID',
  172. 'dataIndex' => 'game_id',
  173. 'width' => 120,
  174. ],
  175. [
  176. 'title' => '游戏',
  177. 'dataIndex' => 'game_name',
  178. 'width' => 120,
  179. ],
  180. [
  181. 'title' => '合计',
  182. 'dataIndex' => 'total',
  183. 'width' => 120,
  184. ]
  185. ];
  186. foreach($dateList as $date){
  187. $columnsData[] = [
  188. 'title' => $date,
  189. 'dataIndex' => $date,
  190. 'width' => 120,
  191. ];
  192. }
  193. $result['data'] = $data;
  194. $result['totalRow'] = $totalRow;
  195. $result['columns'] = $columnsData;
  196. return $result;
  197. }
  198. /*
  199. 数据总览
  200. */
  201. public function getDataOverview($where){
  202. $params = $this->searchByAuth($where);
  203. $whereSql = $this->generateWhereSql($params);
  204. // 基础汇总信息
  205. $field = "
  206. SUM(login_total) AS login_total, -- 登陆总数
  207. SUM(reg_total) AS reg_total, -- 注册总数
  208. SUM(pay_total) AS pay_total, -- 付费总数
  209. SUM(pay_num) AS pay_num, -- 付费人数
  210. SUM(reg_login_total) AS reg_login_total, -- 注册登陆总数
  211. SUM(reg_pay_num) AS reg_pay_num, -- 注册付费数
  212. SUM(reg_pay_total) AS reg_pay_total, -- 注册付费金额
  213. SUM(old_login_total) AS old_login_total, -- 老用户登陆总数
  214. tdate";
  215. $baseData = $this->generateYearUnionList('base_total_day_',$where['reg_date'],$whereSql,$field,'tdate');
  216. if(empty($baseData)){
  217. return [
  218. 'data' => [],
  219. 'totalRow' => []
  220. ];
  221. }
  222. $actWhereSql = str_replace("AND tdate", "AND reg_date", $whereSql);
  223. $actWhereSql .= " AND days = 1";
  224. $actData = $this->generateYearUnionList('game_active_day_',$where['reg_date'],$actWhereSql,'SUM(active_total) AS active_total,reg_date','reg_date');
  225. $actData = array_column($actData,null,'reg_date');
  226. $totalRow = [
  227. 'tdate' => '合计'
  228. ];
  229. foreach($baseData as &$row){
  230. $totalRow['login_total'] = !empty($totalRow['login_total']) ? $totalRow['login_total'] + $row['login_total'] : $row['login_total']; // 总用户 - 登陆总数
  231. $totalRow['reg_login_total'] = !empty($totalRow['reg_login_total']) ? $totalRow['reg_login_total'] + $row['reg_login_total'] : $row['reg_login_total']; // 新用户 - 注册登陆总数
  232. $totalRow['pay_num'] = !empty($totalRow['pay_num']) ? $totalRow['pay_num'] + $row['pay_num'] : $row['pay_num']; // 总用户 - 付费人数
  233. $totalRow['pay_total'] = !empty($totalRow['pay_total']) ? $totalRow['pay_total'] + $row['pay_total'] : $row['pay_total']; // 总用户 - 付费金额
  234. $totalRow['old_login_total'] = !empty($totalRow['old_login_total']) ? $totalRow['old_login_total'] + $row['old_login_total'] : $row['old_login_total']; // 老用户 - 登陆总数
  235. $totalRow['reg_total'] = !empty($totalRow['reg_total']) ? $totalRow['reg_total'] + $row['reg_total'] : $row['reg_total']; // 新用户 - 注册总数
  236. $totalRow['reg_pay_num'] = !empty($totalRow['reg_pay_num']) ? $totalRow['reg_pay_num'] + $row['reg_pay_num'] : $row['reg_pay_num']; // 新用户 - 注册付费数
  237. $totalRow['reg_pay_total'] = !empty($totalRow['reg_pay_total']) ? $totalRow['reg_pay_total'] + $row['reg_pay_total'] : $row['reg_pay_total']; // 新用户 - 注册付费金额
  238. $totalRow['active'] = !empty($totalRow['active']) ? $totalRow['active'] + $actData[$row['tdate']]['active_total']??0 : $actData[$row['tdate']]['active_total']??0; // 次留数
  239. $row['active'] = !empty($actData[$row['tdate']]['active_total']) ? $actData[$row['tdate']]['active_total'] : 0; // 次留数
  240. $row['arpu'] = ToolLogic::getRound($row['pay_total'],$row['pay_num']); // 总用户 - ARPU
  241. $row['pay_rate'] = ToolLogic::getPercent($row['pay_num'],$row['login_total']); // 总用户 - 付费率
  242. $row['reg_pay_rate'] = ToolLogic::getPercent($row['reg_pay_num'],$row['reg_total']); // 新用户 - 注册付费率
  243. $row['reg_arpu'] = ToolLogic::getRound($row['reg_pay_total'],$row['reg_pay_num']); // 新用户 - 注册付费ARPU
  244. $row['act_rate'] = ToolLogic::getPercent($row['active'],$row['reg_total']); // 新用户 - 次留率
  245. $row['old_pay_num'] = $row['pay_num'] - $row['reg_pay_num']; // 老用户 - 付费人数
  246. $row['old_pay_total'] = $row['pay_total'] - $row['reg_pay_total']; // 老用户 - 付费金额
  247. $row['old_pay_rate'] = ToolLogic::getPercent($row['old_pay_num'],$row['old_login_total']); // 老用户 - 付费率
  248. $row['old_arpu'] = ToolLogic::getRound($row['old_pay_total'],$row['old_pay_num']); // 老用户 - 付费ARPU
  249. }
  250. $totalRow['arpu'] = ToolLogic::getRound($totalRow['pay_total'],$totalRow['pay_num']); // 总用户 - ARPU
  251. $totalRow['pay_rate'] = ToolLogic::getPercent($totalRow['pay_num'],$totalRow['login_total']); // 总用户 - 付费率
  252. $totalRow['reg_pay_rate'] = ToolLogic::getPercent($totalRow['reg_pay_num'],$totalRow['reg_total']); // 新用户 - 注册付费率
  253. $totalRow['reg_arpu'] = ToolLogic::getRound($totalRow['reg_pay_total'],$totalRow['reg_pay_num']); // 新用户 - 注册付费ARPU
  254. $totalRow['old_pay_num'] = $totalRow['pay_num'] - $totalRow['reg_pay_num']; // 老用户 - 付费人数
  255. $totalRow['old_pay_total'] = $totalRow['pay_total'] - $totalRow['reg_pay_total']; // 老用户 - 付费金额
  256. $totalRow['old_pay_rate'] = ToolLogic::getPercent($totalRow['old_pay_num'],$totalRow['old_login_total']); // 老用户 - 付费率
  257. $totalRow['old_arpu'] = ToolLogic::getRound($totalRow['old_pay_total'],$totalRow['old_pay_num']); // 老用户 - 付费ARPU
  258. $totalRow['act_rate'] = ToolLogic::getPercent($totalRow['active'],$totalRow['reg_total']); // 次留率
  259. return [
  260. 'data' => $baseData,
  261. 'totalRow' => $totalRow
  262. ];
  263. }
  264. /*
  265. 数据总览(按月)
  266. */
  267. public function getDataOverviewByMonth($where){
  268. $params = $this->searchByAuth($where);
  269. // 根据渠道名称获取渠道ID
  270. if(!empty($params['agent_name'])){
  271. $agentData = Db::connect('db_advert')->query("SELECT id,name FROM agent_list WHERE 1=1 AND name = '{$params['agent_name']}'");
  272. $params['agent_id'] = $agentData[0]['id'] ?? 0;
  273. }
  274. $whereSql = $this->generateWhereSql($params);
  275. // 基础汇总信息
  276. $field = "
  277. SUM(login_total) AS login_total, -- 登陆总数
  278. SUM(reg_total) AS reg_total, -- 注册总数
  279. SUM(pay_total) AS pay_total, -- 付费总数
  280. SUM(pay_num) AS pay_num, -- 付费人数
  281. SUM(reg_login_total) AS reg_login_total, -- 注册登陆总数
  282. SUM(reg_pay_num) AS reg_pay_num, -- 注册付费数
  283. SUM(reg_pay_total) AS reg_pay_total, -- 注册付费金额
  284. SUM(old_login_total) AS old_login_total, -- 老用户登陆总数
  285. date_format(`tdate`, '%Y-%m') AS mdate";
  286. $baseData = $this->generateYearUnionList('base_total_day_',$where['reg_date'],$whereSql,$field,'mdate');
  287. if(empty($baseData)){
  288. return [
  289. 'data' => [],
  290. 'totalRow' => []
  291. ];
  292. }
  293. $actWhereSql = str_replace("AND tdate", "AND reg_date", $whereSql);
  294. $actWhereSql .= " AND days = 1";
  295. $actData = $this->generateYearUnionList('game_active_day_',$where['reg_date'],$actWhereSql,'SUM(active_total) AS active_total,date_format(reg_date, "%Y-%m") AS mdate','mdate');
  296. $actData = array_column($actData,null,'mdate');
  297. $totalRow = [
  298. 'mdate' => '合计'
  299. ];
  300. foreach($baseData as &$row){
  301. $totalRow['login_total'] = !empty($totalRow['login_total']) ? $totalRow['login_total'] + $row['login_total'] : $row['login_total']; // 总用户 - 登陆总数
  302. $totalRow['reg_login_total'] = !empty($totalRow['reg_login_total']) ? $totalRow['reg_login_total'] + $row['reg_login_total'] : $row['reg_login_total']; // 新用户 - 注册登陆总数
  303. $totalRow['pay_num'] = !empty($totalRow['pay_num']) ? $totalRow['pay_num'] + $row['pay_num'] : $row['pay_num']; // 总用户 - 付费人数
  304. $totalRow['pay_total'] = !empty($totalRow['pay_total']) ? $totalRow['pay_total'] + $row['pay_total'] : $row['pay_total']; // 总用户 - 付费金额
  305. $totalRow['old_login_total'] = !empty($totalRow['old_login_total']) ? $totalRow['old_login_total'] + $row['old_login_total'] : $row['old_login_total']; // 老用户 - 登陆总数
  306. $totalRow['reg_total'] = !empty($totalRow['reg_total']) ? $totalRow['reg_total'] + $row['reg_total'] : $row['reg_total']; // 新用户 - 注册总数
  307. $totalRow['reg_pay_num'] = !empty($totalRow['reg_pay_num']) ? $totalRow['reg_pay_num'] + $row['reg_pay_num'] : $row['reg_pay_num']; // 新用户 - 注册付费数
  308. $totalRow['reg_pay_total'] = !empty($totalRow['reg_pay_total']) ? $totalRow['reg_pay_total'] + $row['reg_pay_total'] : $row['reg_pay_total']; // 新用户 - 注册付费金额
  309. $totalRow['active'] = !empty($totalRow['active']) ? $totalRow['active'] + $actData[$row['mdate']]['active_total']??0 : $actData[$row['mdate']]['active_total']??0; // 次留数
  310. $row['active'] = !empty($actData[$row['mdate']]['active_total']) ? $actData[$row['mdate']]['active_total'] : 0; // 次留数
  311. $row['arpu'] = ToolLogic::getRound($row['pay_total'],$row['pay_num']); // 总用户 - ARPU
  312. $row['pay_rate'] = ToolLogic::getPercent($row['pay_num'],$row['login_total']); // 总用户 - 付费率
  313. $row['reg_pay_rate'] = ToolLogic::getPercent($row['reg_pay_num'],$row['reg_total']); // 新用户 - 注册付费率
  314. $row['reg_arpu'] = ToolLogic::getRound($row['reg_pay_total'],$row['reg_pay_num']); // 新用户 - 注册付费ARPU
  315. $row['act_rate'] = ToolLogic::getPercent($row['active'],$row['reg_total']); // 新用户 - 次留率
  316. $row['old_pay_num'] = $row['pay_num'] - $row['reg_pay_num']; // 老用户 - 付费人数
  317. $row['old_pay_total'] = $row['pay_total'] - $row['reg_pay_total']; // 老用户 - 付费金额
  318. $row['old_pay_rate'] = ToolLogic::getPercent($row['old_pay_num'],$row['old_login_total']); // 老用户 - 付费率
  319. $row['old_arpu'] = ToolLogic::getRound($row['old_pay_total'],$row['old_pay_num']); // 老用户 - 付费ARPU
  320. }
  321. $totalRow['arpu'] = ToolLogic::getRound($totalRow['pay_total'],$totalRow['pay_num']); // 总用户 - ARPU
  322. $totalRow['pay_rate'] = ToolLogic::getPercent($totalRow['pay_num'],$totalRow['login_total']); // 总用户 - 付费率
  323. $totalRow['reg_pay_rate'] = ToolLogic::getPercent($totalRow['reg_pay_num'],$totalRow['reg_total']); // 新用户 - 注册付费率
  324. $totalRow['reg_arpu'] = ToolLogic::getRound($totalRow['reg_pay_total'],$totalRow['reg_pay_num']); // 新用户 - 注册付费ARPU
  325. $totalRow['old_pay_num'] = $totalRow['pay_num'] - $totalRow['reg_pay_num']; // 老用户 - 付费人数
  326. $totalRow['old_pay_total'] = $totalRow['pay_total'] - $totalRow['reg_pay_total']; // 老用户 - 付费金额
  327. $totalRow['old_pay_rate'] = ToolLogic::getPercent($totalRow['old_pay_num'],$totalRow['old_login_total']); // 老用户 - 付费率
  328. $totalRow['old_arpu'] = ToolLogic::getRound($totalRow['old_pay_total'],$totalRow['old_pay_num']); // 老用户 - 付费ARPU
  329. $totalRow['act_rate'] = ToolLogic::getPercent($totalRow['active'],$totalRow['reg_total']); // 次留率
  330. return [
  331. 'data' => $baseData,
  332. 'totalRow' => $totalRow
  333. ];
  334. }
  335. /**
  336. * 收入分析
  337. */
  338. public function getIncomeAnalysis($where){
  339. $params = $this->searchByAuth($where);
  340. $tdate = $params['reg_date']??date('Y-m-d');
  341. $ldate = date('Y-m-d', strtotime($tdate . ' -1 days'));
  342. $wdate = date('Y-m-d', strtotime($tdate . ' -7 days'));
  343. unset($params['reg_date']);
  344. $whereSql = $this->generateWhereSql($params);
  345. $whereSql .= " AND tdate IN ('{$tdate}','{$ldate}','{$wdate}')";
  346. $field = "
  347. SUM(pay_total) AS pay_total, -- 付费金额
  348. SUM(pay_num) AS pay_num, -- 付费人数
  349. SUM(login_total) AS login_total, -- 登陆总数
  350. game_id,
  351. tdate";
  352. $year = (int)date('Y', strtotime($tdate));
  353. $tableName = 'base_total_day_'.$year;
  354. $baseData = Db::connect('db_data_report')->query("SELECT {$field} FROM {$tableName} WHERE 1=1 {$whereSql} GROUP BY game_id,tdate");
  355. if(empty($baseData)){
  356. return [
  357. 'data' => [],
  358. 'totalRow' => []
  359. ];
  360. }
  361. // 计算今日,所有游戏总充值
  362. $totalRow = [
  363. 'game_id' => '合计',
  364. ];
  365. $allTotal = 0;
  366. $data = [];
  367. foreach($baseData as &$row){
  368. // 查询日期数据
  369. if($row['tdate'] == $tdate){
  370. $gameId = $row['game_id'];
  371. $data[$gameId]['game_id'] = $gameId;
  372. $data[$gameId]['login_total'] = $row['login_total']; // DAU
  373. $data[$gameId]['pay_total'] = $row['pay_total']??0; // 今日充值
  374. $data[$gameId]['pay_num'] = $row['pay_num']??0; // 今日付费人数
  375. $data[$gameId]['pay_arpu'] = ToolLogic::getRound($row['pay_total'],$row['pay_num']); // 今日付费ARPU
  376. $allTotal += $row['pay_total'];
  377. $totalRow['pay_total'] = !empty($totalRow['pay_total']) ? $totalRow['pay_total'] + $row['pay_total'] : $row['pay_total']; // 今日充值
  378. $totalRow['pay_num'] = !empty($totalRow['pay_num']) ? $totalRow['pay_num'] + $row['pay_num'] : $row['pay_num']; // 今日付费人数
  379. $totalRow['login_total'] = !empty($totalRow['login_total']) ? $totalRow['login_total'] + $row['login_total'] : $row['login_total']; // 今日登陆人数
  380. }
  381. // 查询昨天数据
  382. if($row['tdate'] == $ldate){
  383. $gameId = $row['game_id'];
  384. $data[$gameId]['yestoday_pay_total'] = $row['pay_total']??0; // 昨日充值
  385. $totalRow['yestoday_pay_total'] = !empty($totalRow['yestoday_pay_total']) ? $totalRow['yestoday_pay_total'] + $row['pay_total'] : $row['pay_total']; // 昨日充值
  386. }
  387. // 查询7天前数据
  388. if($row['tdate'] == $wdate){
  389. $gameId = $row['game_id'];
  390. $data[$gameId]['week_pay_total'] = $row['pay_total']??0; // 7天前充值
  391. $totalRow['week_pay_total'] = !empty($totalRow['week_pay_total']) ? $totalRow['week_pay_total'] + $row['pay_total'] : $row['pay_total']; // 7天前充值
  392. }
  393. }
  394. $totalRow['pay_arpu'] = ToolLogic::getRound($totalRow['pay_total'],$totalRow['pay_num']); // 今日充值ARPU
  395. $totalRow['pay_ratio'] = ToolLogic::getPercent($totalRow['pay_total'],$allTotal); // 今日充值占比
  396. $totalRow['pay_increase_yestoday'] = $totalRow['pay_total'] - $totalRow['yestoday_pay_total']; // 昨日增长
  397. $totalRow['pay_increase_week'] = $totalRow['pay_total'] - $totalRow['week_pay_total']; // 7天增长
  398. foreach($data as &$row){
  399. $row['pay_ratio'] = ToolLogic::getPercent($row['pay_total'],$allTotal); // 今日充值占比
  400. $row['pay_increase_yestoday'] = $row['pay_total'] - $row['yestoday_pay_total']; // 昨日增长
  401. $row['pay_increase_week'] = $row['pay_total'] - $row['week_pay_total']; // 7天增长
  402. }
  403. return [
  404. 'data' => array_values($data),
  405. 'totalRow' => $totalRow
  406. ];
  407. }
  408. /**
  409. * 付费留存
  410. * 1. 登录日志表:sdk_login_log_, 查找符合注册时间的用户, 获取用户id
  411. *
  412. * inner join ON login.uid = order.uid,
  413. *
  414. * 2. 根据用户id,去订单表,筛选出,次留、2留的日期为充值日期, 从而获取充值人数
  415. * 3. 根据注册时间,获取总的pay_num
  416. */
  417. public function getPayRetention($where){
  418. $params = $this->searchByAuth($where);
  419. // $whereSql = $this->generateWhereSql($params);
  420. // 判断不能超过90天查询
  421. $days = ToolLogic::getDays($where['reg_date'][0],$where['reg_date'][1]);
  422. if($days > 90){
  423. throw new ApiException('时间查询范围请勿超过90天');
  424. }
  425. $whereRaw = '1=1';
  426. if(!empty($params['game_id'])){
  427. $whereRaw .= " AND game_id IN(".implode(',',$params['game_id']).")";
  428. }
  429. if(!empty($params['media_id'])){
  430. $whereRaw .= " AND media_id = ({$params['media_id']})";
  431. }
  432. if(!empty($params['agent_id'])){
  433. $whereRaw .= " AND agent_id IN(".implode(',',$params['agent_id']).")";
  434. }
  435. // 1. 根据注册时间,获取注册付费人数
  436. $payData = Db::connect('db_game_log')->query("
  437. SELECT
  438. SUBSTRING(reg_date,1,10) as dimension, -- 注册日期
  439. COUNT(DISTINCT uid) as pay_num -- 注册付费人数
  440. FROM sdk_order_success
  441. WHERE {$whereRaw} AND reg_date BETWEEN '{$params['reg_date'][0]} 00:00:00' AND '{$params['reg_date'][1]} 23:59:59'
  442. GROUP BY
  443. dimension
  444. ");
  445. $payDataMap = array_column($payData,null,'dimension');
  446. // 2. 计算留存付费的人数
  447. $sqlArr = [];
  448. $medate = date("Y-m-d", strtotime( "+ 60 day", strtotime($params['reg_date'][1])));
  449. $tableNames = ToolLogic::getMonthlyTableNames('sdk_login_log_', $params['reg_date'][0], $medate);
  450. foreach($tableNames as $tableName){
  451. $sqlArr[] = "
  452. SELECT
  453. CONCAT(FROM_UNIXTIME(reg_time, '%Y-%m-%d'), '|', TIMESTAMPDIFF(DAY, FROM_UNIXTIME(reg_time), FROM_UNIXTIME(login_time))) AS dimension, -- 注册日期|留存天数
  454. FROM_UNIXTIME(reg_time, '%Y-%m-%d') AS reg_date, -- 注册日期
  455. TIMESTAMPDIFF(DAY, FROM_UNIXTIME(reg_time), FROM_UNIXTIME(login_time)) AS day_num, -- 留存天数
  456. COUNT(DISTINCT a.user_name) AS remain_num -- 留存人数
  457. FROM {$tableName} AS a
  458. INNER JOIN (
  459. SELECT
  460. DISTINCT user_name
  461. FROM sdk_order_success
  462. WHERE
  463. {$whereRaw} AND reg_date BETWEEN '{$params['reg_date'][0]} 00:00:00' AND '{$params['reg_date'][1]} 23:59:59'
  464. ) AS b ON a.user_name = b.user_name
  465. WHERE
  466. {$whereRaw} AND reg_time BETWEEN ".strtotime($params['reg_date'][0]." 00:00:00")." AND ".strtotime($params['reg_date'][1]." 23:59:59")."
  467. GROUP BY dimension
  468. ";
  469. }
  470. $sql = implode(" UNION ALL ", $sqlArr);
  471. $remainData = Db::connect('db_game_log')->query($sql);
  472. $remainData = $remainData ? array_column($remainData, null, "dimension") : [];
  473. $regDateRange = ToolLogic::getDatesBetween($params['reg_date'][0],$params['reg_date'][1]);
  474. $remainRange = [];
  475. for ($i=2; $i<=30; $i++){
  476. $remainRange[] = $i;
  477. }
  478. $remainRange = array_merge($remainRange, [35,40,45,50,55,60]);
  479. $data = [];
  480. foreach ($regDateRange as $regDate){
  481. $row['reg_date'] = $regDate;
  482. $row['reg_pay_num'] = $payDataMap[$regDate]['pay_num'] ?? 0;
  483. foreach ($remainRange as $remainNum){
  484. $dimension = $regDate . "|" . ($remainNum-1);
  485. $row['remain_' . $remainNum] = $remainData[$dimension]['remain_num'] ?? 0;
  486. }
  487. $data[] = $row;
  488. }
  489. // 合计
  490. $totalRow = [
  491. 'reg_date' => '合计',
  492. ];
  493. // 计算合计
  494. if($data) foreach ($data as $item){
  495. $totalRow['reg_pay_num'] = $totalRow['reg_pay_num'] ?? 0;
  496. $totalRow['reg_pay_num'] += $item['reg_pay_num'];
  497. foreach ($remainRange as $remainNum){
  498. $key = 'remain_'.$remainNum;
  499. $totalRow[$key] = $totalRow[$key] ?? 0;
  500. $totalRow[$key] += $item[$key];
  501. }
  502. }
  503. // 计算比率
  504. if ($params['show_type'] == 'rate') {
  505. if($data) foreach ($remainRange as $remainNum) {
  506. $key = 'remain_' . $remainNum;
  507. $totalRow[$key] = ToolLogic::getPercent($totalRow[$key], $totalRow['reg_pay_num']);
  508. foreach ($data as &$val) {
  509. $val[$key] = ToolLogic::getPercent($val[$key], $val['reg_pay_num']);
  510. }
  511. }
  512. }
  513. return [
  514. 'data' => $data,
  515. 'totalRow' => $totalRow
  516. ];
  517. }
  518. // 图表数据
  519. public function getChartData($where){
  520. $params = $this->searchByAuth($where);
  521. $type = $params['compare_type']??'day';
  522. // 如果按照天对比
  523. if($type === 'day'){
  524. $data1 = [];
  525. $data2 = [];
  526. $data1Res = [];
  527. $data2Res = [];
  528. $field = "
  529. SUM(reg_total) as reg, -- 注册人数
  530. SUM(old_login_total) as login, -- 老用户登陆人数
  531. SUM(pay_total) as pay, -- 付费金额
  532. tdate
  533. ";
  534. // 获取对比日期1的数据, 注册、登录、充值
  535. $params['reg_date'] = $params['compare_date1'];
  536. $whereSql1 = $this->generateWhereSql($params);
  537. $baseData1 = $this->generateYearUnionList('base_total_day_',$params['compare_date1'],$whereSql1,$field,'tdate');
  538. foreach($baseData1 as $item){
  539. $data1Res[$item['tdate']]['reg'] = $item['reg'];
  540. $data1Res[$item['tdate']]['pay'] = $item['pay'];
  541. $data1Res[$item['tdate']]['login'] = $item['login'];
  542. }
  543. // 获取对比日期2的数据, 注册、登录、充值
  544. $params['reg_date'] = $params['compare_date2'];
  545. $whereSql2 = $this->generateWhereSql($params);
  546. $baseData2 = $this->generateYearUnionList('base_total_day_',$params['compare_date2'],$whereSql2,$field,'tdate');
  547. foreach($baseData2 as $item){
  548. $data2Res[$item['tdate']]['reg'] = $item['reg'];
  549. $data2Res[$item['tdate']]['pay'] = $item['pay'];
  550. $data2Res[$item['tdate']]['login'] = $item['login'];
  551. }
  552. // 获取消耗数据1
  553. $params['reg_date'] = $params['compare_date1'];
  554. $costWhereSql1 = $this->generateWhereSql($params);
  555. echo $costWhereSql1;
  556. $costData1 = Db::connect('db_advert')->query("
  557. SELECT SUM(money) as money, tdate
  558. FROM media_cost
  559. WHERE 1=1 {$costWhereSql1}
  560. GROUP BY tdate
  561. ");
  562. foreach($costData1 as $item){
  563. $data1Res[$item['tdate']]['cost'] = $item['money'];
  564. }
  565. // 获取消耗数据2
  566. $params['reg_date'] = $params['compare_date2'];
  567. $costWhereSql2 = $this->generateWhereSql($params);
  568. $costData2 = Db::connect('db_advert')->query("
  569. SELECT SUM(money) as money, tdate
  570. FROM media_cost
  571. WHERE 1=1 {$costWhereSql2}
  572. GROUP BY tdate
  573. ");
  574. foreach($costData2 as $item){
  575. $data2Res[$item['tdate']]['cost'] = $item['money'];
  576. }
  577. // 获取两个日期之间的所有日期
  578. $day1Date = ToolLogic::getDatesBetween($params['compare_date1'][0],$params['compare_date1'][1]);
  579. $day2Date = ToolLogic::getDatesBetween($params['compare_date2'][0],$params['compare_date2'][1]);
  580. foreach($day1Date as $k=>$d){
  581. $data1['days'][$k] = $d;
  582. $data1['pay'][$k] = !empty($data1Res[$d]['pay']) ? round((float)$data1Res[$d]['pay'], 2) : 0;
  583. $data1['cost'][$k] = !empty($data1Res[$d]['cost']) ? round((float)$data1Res[$d]['cost'], 2) : 0;
  584. $data1['reg'][$k] = !empty($data1Res[$d]['reg']) ? (int)$data1Res[$d]['reg'] : 0;
  585. $data1['login'][$k]= !empty($data1Res[$d]['login']) ? (int)$data1Res[$d]['login'] : 0;
  586. }
  587. foreach($day2Date as $k=>$d){
  588. $data2['days'][$k] = $d;
  589. $data2['pay'][$k] = !empty($data2Res[$d]['pay']) ? round((float)$data2Res[$d]['pay'], 2) : 0;
  590. $data2['cost'][$k] = !empty($data2Res[$d]['cost']) ? round((float)$data2Res[$d]['cost'], 2) : 0;
  591. $data2['reg'][$k] = !empty($data2Res[$d]['reg']) ? (int)$data2Res[$d]['reg'] : 0;
  592. $data2['login'][$k]= !empty($data2Res[$d]['login']) ? (int)$data2Res[$d]['login'] : 0;
  593. }
  594. // 格式化x轴的时间
  595. $forData = [];
  596. $days1 = [];
  597. $days2 = [];
  598. if(count($data1['days'])>count($data2['days'])){
  599. $forData = $data1['days'];
  600. }else{
  601. $forData = $data2['days'];
  602. }
  603. for($i=0;$i<count($forData);$i++){
  604. $d1 = !empty($data1['days'][$i]) ? date("m-d", strtotime($data1['days'][$i])) : "";
  605. $d2 = !empty($data2['days'][$i]) ? date("m-d", strtotime($data2['days'][$i])) : "";
  606. $days1[] = $d1;
  607. $days2[] = $d2;
  608. }
  609. $data1['series'] = "日期1";
  610. $data2['series'] = "日期2";
  611. return [
  612. 'data1' => $data1,
  613. 'data2' => $data2,
  614. 'days1' => $days1,
  615. 'days2' => $days2
  616. ];
  617. }
  618. // 如果按小时对比
  619. if($type === 'hour'){
  620. $data1 = [];
  621. $data2 = [];
  622. $data1Res = [];
  623. $data2Res = [];
  624. $field = "
  625. SUM(reg_total) as reg, -- 注册人数
  626. SUM(old_login_total) as login, -- 老用户登陆人数
  627. SUM(pay_total) as pay, -- 付费金额
  628. SUM(cost) as cost, -- 消耗金额
  629. thour
  630. ";
  631. // 获取对比日期1的数据, 注册、登录、充值
  632. $params['reg_date'] = $params['compare_date1_date'];
  633. $whereSql1 = $this->generateWhereSql($params);
  634. $baseData1 = $this->generateMonthUnionList('base_total_hour_',$params['compare_date1'],$whereSql1,$field,'thour');
  635. foreach($baseData1 as $item){
  636. $data1Res[$item['thour']]['reg'] = $item['reg'];
  637. $data1Res[$item['thour']]['pay'] = $item['pay'];
  638. $data1Res[$item['thour']]['login'] = $item['login'];
  639. $data1Res[$item['thour']]['cost'] = $item['cost'];
  640. }
  641. // 获取对比日期2的数据, 注册、登录、充值
  642. $params['reg_date'] = $params['compare_date2_date'];
  643. $whereSql2 = $this->generateWhereSql($params);
  644. echo $whereSql2;
  645. $baseData2 = $this->generateMonthUnionList('base_total_hour_',$params['compare_date2'],$whereSql2,$field,'thour');
  646. foreach($baseData2 as $item){
  647. $data2Res[$item['thour']]['reg'] = $item['reg'];
  648. $data2Res[$item['thour']]['pay'] = $item['pay'];
  649. $data2Res[$item['thour']]['login'] = $item['login'];
  650. $data2Res[$item['thour']]['cost'] = $item['cost'];
  651. }
  652. $ndate = date("Y-m-d");
  653. $hour = date("H");
  654. print_r($data1Res);
  655. for ($h=0; $h<24; $h++){
  656. if($params['compare_date1_date']==$ndate && $h>$hour){
  657. continue;
  658. }
  659. $data1['hour'][$h] = $h;
  660. $data1['pay'][$h] = !empty($data1Res[$h]) ? round((float)$data1Res[$h]['pay']??0, 2) : 0;
  661. $data1['cost'][$h] = !empty($data1Res[$h]) ? round((float)$data1Res[$h]['cost']??0, 2) : 0;
  662. $data1['reg'][$h] = !empty($data1Res[$h]) ? (int)$data1Res[$h]['reg']??0 : 0;
  663. $data1['login'][$h] = !empty($data1Res[$h]) ? (int)$data1Res[$h]['login']??0 : 0;
  664. }
  665. for($h=0; $h<24; $h++){
  666. if($params['compare_date2_date']==$ndate && $h>$hour){
  667. continue;
  668. }
  669. $data2['hour'][$h] = $h;
  670. $data2['pay'][$h] = !empty($data2Res[$h]) ? round((float)$data2Res[$h]['pay']??0, 2) : 0;
  671. $data2['cost'][$h] = !empty($data2Res[$h]) ? round((float)$data2Res[$h]['cost']??0, 2) : 0;
  672. $data2['reg'][$h] = !empty($data2Res[$h]) ? (int)$data2Res[$h]['reg']??0 : 0;
  673. $data2['login'][$h] = !empty($data2Res[$h]) ? (int)$data2Res[$h]['login']??0 : 0;
  674. }
  675. $hour = [];
  676. for ($h=0; $h<24; $h++){
  677. $hour[] = $h;
  678. }
  679. $data1['series'] = $params['compare_date1_date'];
  680. $data2['series'] = $params['compare_date2_date'];
  681. return [
  682. 'data1' => $data1,
  683. 'data2' => $data2,
  684. 'days1' => $hour,
  685. 'days2' => $hour
  686. ];
  687. }
  688. }
  689. // 生成基础日统计表的联合查询列表
  690. public function generateYearUnionList($namePrefix, $regDate,$whereSql='',$field='*',$group=null){
  691. $tableNames = ToolLogic::getYearlyTableNames($namePrefix, $regDate[0],$regDate[1]);
  692. $sqlParts = [];
  693. foreach ($tableNames as $tableName){
  694. $sqlParts[] = "SELECT * FROM {$tableName} WHERE 1=1 {$whereSql}";
  695. }
  696. $unionSql = implode(" UNION ALL ", $sqlParts);
  697. $finalSql = "
  698. SELECT {$field} FROM ( {$unionSql} ) AS all_total_day
  699. ";
  700. if (!empty($group)) {
  701. $finalSql .= " GROUP BY {$group}";
  702. }
  703. $baseData = Db::connect('db_data_report')->query($finalSql);
  704. return $baseData;
  705. }
  706. // 生成基础小时统计表的联合查询列表
  707. public function generateMonthUnionList($namePrefix, $regDate,$whereSql='',$field='*',$group=null){
  708. $tableNames = ToolLogic::getMonthlyTableNames($namePrefix, $regDate[0],$regDate[1]);
  709. $sqlParts = [];
  710. foreach ($tableNames as $tableName){
  711. $sqlParts[] = "SELECT * FROM {$tableName} WHERE 1=1 {$whereSql}";
  712. }
  713. $unionSql = implode(" UNION ALL ", $sqlParts);
  714. $finalSql = "
  715. SELECT {$field} FROM ( {$unionSql} ) AS all_total_day
  716. ";
  717. if (!empty($group)) {
  718. $finalSql .= " GROUP BY {$group}";
  719. }
  720. $baseData = Db::connect('db_data_report')->query($finalSql);
  721. return $baseData;
  722. }
  723. // 生成wheresql
  724. public function generateWhereSql($params){
  725. $whereSql = "";
  726. // 游戏id
  727. if(!empty($params['game_id'])){
  728. if (is_array($params['game_id'])) {
  729. $whereSql .= " AND game_id IN(" . implode(',', $params['game_id']) . ")";
  730. } else {
  731. $whereSql .= " AND game_id = {$params['game_id']}";
  732. }
  733. }
  734. // 媒体id
  735. if(!empty($params['media_id'])){
  736. $whereSql .= " AND media_id = {$params['media_id']}";
  737. }
  738. // 渠道id
  739. if(!empty($params['agent_id'])){
  740. $whereSql .= " AND agent_id = {$params['agent_id']}";
  741. }
  742. // 广告位id
  743. if(!empty($params['site_id'])){
  744. if (is_array($params['site_id'])) {
  745. $whereSql .= " AND site_id IN(" . implode(',', $params['site_id']) . ")";
  746. } else {
  747. $whereSql .= " AND site_id = {$params['site_id']}";
  748. }
  749. }
  750. // 负责人
  751. if(!empty($params['auth_id'])){
  752. if (is_array($params['auth_id'])) {
  753. $whereSql .= " AND auth_id IN(" . implode(',', $params['auth_id']) . ")";
  754. } else {
  755. $whereSql .= " AND auth_id = {$params['auth_id']}";
  756. }
  757. }
  758. // 注册日期
  759. if(!empty($params['reg_date']) && is_array($params['reg_date'])){
  760. $whereSql .= " AND tdate BETWEEN '{$params['reg_date'][0]}' AND '{$params['reg_date'][1]}'";
  761. }
  762. // 注册日期,不是数组,则认为是单个日期
  763. if(!empty($params['reg_date']) && !is_array($params['reg_date'])){
  764. $whereSql .= " AND tdate = '{$params['reg_date']}'";
  765. }
  766. return $whereSql;
  767. }
  768. }