123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- <?php
- declare (strict_types=1);
- namespace app\store\controller\analysis;
- use app\common\model\analysis\AnalysisDailyRetainTag;
- use app\store\controller\Controller;
- use app\store\model\analysis\AnalysisDailyRetain as AnalysisDailyRetainModel;
- use app\store\model\analysis\AnalysisWeeklyRetain as AnalysisWeeklyRetainModel;
- use app\store\model\analysis\AnalysisMonthlyRetain as AnalysisMonthlyRetainModel;
- use app\common\service\Export as ExportService;
- /**
- * 留存分析
- *
- * Class Retain
- * @package app\store\controller\analysis
- */
- class Retain extends Controller
- {
- public function exportRetainData(){
- $params = $this->request->param();
- $type = $params['type'] ?? 2; // 时间筛选类型 1-最近7天 2-最近30天 3-自定义
- $start = (int)($params['start'] ?? '');
- $end = (int)($params['end'] ?? '');
- $retain_type = $params['retain_type'] ?? 1; // 类型 1-新增用户留存 2-活跃用户留存
- $grain_size = $params['grain_size'] ?? 1; // 粒度 1-日粒度 2-周粒度 3-月粒度
- if ($type == 3 && (!$start || !$end)) {
- return $this->renderError('自定义区间时间不能为空');
- }
- // 根据时间筛选类型计算筛选开始结束时间
- if ($type == 1) { //最近7天
- $start = strtotime('-7 days');
- $end = strtotime('-1 days');
- } elseif ($type == 2) {//最近30天
- $start = strtotime('-30 days');
- $end = strtotime('-1 days');
- }
- $table = $this->getChartTables($start, $end, $retain_type, $grain_size);
-
- $data = [];
- $data['header'] = ['序号', '时间', '新增用户数','1天后','2天后','3天后','4天后','5天后','6天后','7天后','14天后','30天后'];
- $data['filename'] = '用户留存分析';
- $data['data'] = [];
- foreach ($table as $k=>$arr){
- $new_list['key'] = $k+1;
- $new_list['ref_date'] = $arr['ref_date'];
- $new_list['retain_0'] = $arr['retain_0'];
- $new_list['retain_1'] = $arr['retain_1'];
- $new_list['retain_2'] = $arr['retain_2'];
- $new_list['retain_3'] = $arr['retain_3'];
- $new_list['retain_4'] = $arr['retain_4'];
- $new_list['retain_5'] = $arr['retain_5'];
- $new_list['retain_6'] = $arr['retain_6'];
- $new_list['retain_7'] = $arr['retain_7'];
- $new_list['retain_14'] = $arr['retain_14'];
- $new_list['retain_30'] = $arr['retain_30'];
- $data['data'][] = $new_list;
- }
- $res = ExportService::export($data['data'],$data['header'],$data['filename'],'列表','Xls');
- return $this->renderSuccess($res,'导出成功');
- }
- /**
- * 留存数据
- *
- * @return array
- */
- public function retainData()
- {
- $params = $this->request->param();
- $type = $params['type'] ?? 2; // 时间筛选类型 1-最近7天 2-最近30天 3-自定义
- $start = (int)($params['start'] ?? '');
- $end = (int)($params['end'] ?? '');
- $retain_type = $params['retain_type'] ?? 1; // 类型 1-新增用户留存 2-活跃用户留存
- $grain_size = $params['grain_size'] ?? 1; // 粒度 1-日粒度 2-周粒度 3-月粒度
- if ($type == 3 && (!$start || !$end)) {
- return $this->renderError('自定义区间时间不能为空');
- }
- // 根据时间筛选类型计算筛选开始结束时间
- if ($type == 1) { //最近7天
- $start = strtotime('-7 days');
- $end = strtotime('-1 days');
- } elseif ($type == 2) {//最近30天
- $start = strtotime('-30 days');
- $end = strtotime('-1 days');
- }
- $table = $this->getChartTables($start, $end, $retain_type, $grain_size);
- $data = [
- 'start' => date('Y-m-d', $start),
- 'end' => date('Y-m-d', $end),
- 'table' => $table
- ];
- return $this->renderSuccess($data);
- }
- private function getChartTables($start, $end, $retain_type, $grain_size)
- {
- $start = strtotime(date('Y-m-d', $start));
- $end = strtotime(date('Y-m-d', $end));
- if ($retain_type == AnalysisDailyRetainTag::TYPE_NEW) {
- $with = 'retainTagNew';
- } elseif($retain_type == AnalysisDailyRetainTag::TYPE_ACTIVE) {
- $with = 'retainTagActive';
- } else {
- return $this->renderError('留存类型参数无效');
- }
- $retainDays = self::getRetainDays($grain_size);
- if ($grain_size == 1) { // 日粒度
- $retainModel = new AnalysisDailyRetainModel();
- } elseif ($grain_size == 2) { // 周粒度
- $retainModel = new AnalysisWeeklyRetainModel();
- // 判断开始时间是否不满一周
- if (date("w",$start) != 1) {
- $start = strtotime('-1 monday', $start);
- }
- } elseif ($grain_size == 3) { // 月粒度
- $retainModel = new AnalysisMonthlyRetainModel();
- // 判断开始时间是否不满一月
- if (date("Y-m",$start) == date("Y-m")) {
- $start = strtotime(last_month('Y-m', 2, $start));
- } else {
- $start = strtotime(last_month('Y-m', 1, $start));
- }
- }
- $list = $retainModel::where('start_time', '>=', $start)
- ->where('end_time', '<', $end+ 86400)
- ->field('id,ref_date')
- ->with($with)
- ->order('ref_date', 'desc')
- ->paginate()
- ->each(function ($v) use ($with, $retainDays) {
- $tags = [];
- foreach ($v[$with] as $vv) {
- $tags[$vv['key']] = $vv['value'];
- }
- foreach ($retainDays as $kk=>$rd) {
- $retain_first = $tags[0]; // 当日
- if (isset($tags[$rd])) {
- if ($rd > 0) {
- if ($tags[$rd] > 0 && $retain_first > 0) {
- $v["retain_{$rd}"] = round(($tags[$rd] / $retain_first)*100, 2);
- } else {
- $v["retain_{$rd}"] = 0;
- }
- } else {
- $v["retain_{$rd}"] = $tags[$rd];
- }
- } else {
- $v["retain_{$rd}"] = '';
- }
- }
- unset($v['id'],$v[$with]);
- });
- return $list;
- }
- private static function getRetainDays($grain_size)
- {
- if ($grain_size == 1) {
- return [0,1,2,3,4,5,6,7,14,30];
- } elseif ($grain_size == 2) {
- return [0,1,2,3,4];
- } elseif ($grain_size == 3) {
- return [0,1];
- } else {
- return [];
- }
- }
- }
|