618 lines
21 KiB
PHP
618 lines
21 KiB
PHP
<?php
|
||
|
||
namespace app\controller\backend;
|
||
|
||
use app\exception\BadSysSettingException;
|
||
use app\model\BaiduTjGather;
|
||
use app\model\SeoAccount;
|
||
use app\model\SysSetting;
|
||
use app\model\Visit;
|
||
use app\model\VisitLog;
|
||
use app\model\Website;
|
||
use think\facade\Lang;
|
||
|
||
class StatisticsController extends BaseController
|
||
{
|
||
public $header = '';
|
||
public $url = 'http://api.baidu.com/json/tongji/v1/ReportService/getData';
|
||
protected $baiduInfo;
|
||
private $site_id = 0;
|
||
|
||
/**
|
||
* @throws \app\exception\ModelException
|
||
*/
|
||
public function setConfig()
|
||
{
|
||
$id = input('param.id') ?? 0;
|
||
if (!empty($id)) {
|
||
|
||
$info = (new SeoAccount())->where('id', $id)->find();
|
||
$this->baiduInfo = [
|
||
'account_type' => '1',
|
||
'username' => $info['account'],
|
||
'password' => $info['password'],
|
||
'token' => $info['token'],
|
||
];
|
||
} else {
|
||
$this->baiduInfo = null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @throws \app\exception\ModelException
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function initialize()
|
||
{
|
||
parent::initialize();
|
||
}
|
||
|
||
/**
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function baiduErrorReturn($response)
|
||
{
|
||
if(!empty($response['header']['failures'])){
|
||
throw new BadSysSettingException($response['header']['failures'][0]['message']);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function getResponse($data)
|
||
{
|
||
$data = json_encode(['body'=>$data, "header"=>$this->header]);
|
||
$response = $this->https_request($this->url, $data);
|
||
$response = json_decode($response,true);
|
||
$this->baiduErrorReturn($response);
|
||
return $response;
|
||
}
|
||
|
||
/**
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function lists(): \think\response\Json
|
||
{
|
||
$url = 'https://api.baidu.com/json/tongji/v1/ReportService/getSiteList';
|
||
$data = json_encode(["header"=>$this->header]);
|
||
$response = $this->https_request($url, $data);
|
||
$response = json_decode($response, true);
|
||
$this->baiduErrorReturn($response);
|
||
return jsonReturn(0, Lang::get('查询成功'), $response['body']['data']['0']['list']);
|
||
}
|
||
|
||
public function indexLists()
|
||
{
|
||
$websiteModel = new Website();
|
||
$list = $websiteModel->field('*, id as site_id, domain')->select();
|
||
return jsonReturn(0, Lang::get('查询成功'), $list);
|
||
}
|
||
|
||
// 首页趋势图
|
||
public function indexQST()
|
||
{
|
||
ini_set('memory_limit', '512M');
|
||
|
||
$websiteId = $this->request->request('website_id')?$this->request->request('website_id'):1;
|
||
$type = $this->request->request('type')?$this->request->request('type'):1;
|
||
|
||
$nowDay = date('Y-m-d');
|
||
// 今天
|
||
$startTime = strtotime($nowDay);
|
||
$endTime = strtotime(date('Y-m-d', strtotime('+1 day')));
|
||
if ($type==2) { // 昨天
|
||
$startTime = strtotime(date('Y-m-d', strtotime('-1 day')));
|
||
$endTime = strtotime($nowDay) - 1;
|
||
} elseif ($type==3) { // 最近7天
|
||
$startTime = strtotime(date('Y-m-d', strtotime('-6 day')));
|
||
$endTime = strtotime(date('Y-m-d', strtotime('+1 day')));
|
||
} elseif ($type==4) { // 最近30天
|
||
$startTime = strtotime(date('Y-m-d', strtotime('-29 day')));
|
||
$endTime = strtotime(date('Y-m-d', strtotime('+1 day')));
|
||
}
|
||
|
||
$visitModel = new VisitLog();
|
||
|
||
$list = $visitModel->where([
|
||
['create_time', '>=', $startTime],
|
||
['create_time', '<=', $endTime],
|
||
['website_id', '=', $websiteId],
|
||
])->select()->toArray();
|
||
|
||
$newList = [];
|
||
|
||
if ($type == 1 || $type == 2) {
|
||
$maxH = 23;
|
||
if ($type == 1) {
|
||
$maxH = date('H');
|
||
}
|
||
|
||
for ($i = 0; $i <= $maxH; $i++) {
|
||
if ($i < 10) {
|
||
$i = '0' . $i;
|
||
}
|
||
$i = (string)$i;
|
||
|
||
$newList[$i] = 0;
|
||
}
|
||
} else {
|
||
for ($i = $startTime; $i <= $endTime;) {
|
||
$dateStr = date('Y-m-d', $i);
|
||
$newList[$dateStr] = 0;
|
||
$i += 86400;
|
||
}
|
||
}
|
||
|
||
$type1List = $type2List = $type3List = $newList;
|
||
|
||
$type2Unique = []; // 校验唯一
|
||
$type3Unique = []; // 校验唯一
|
||
|
||
// type 为1和2,时间间隔为小时。否则为天
|
||
foreach ($list as $value) {
|
||
if ($type == 1 || $type == 2) {
|
||
$key = date('H', strtotime($value['create_time']));
|
||
} else {
|
||
$key = date('Y-m-d', strtotime($value['create_time']));
|
||
}
|
||
$type1List[$key] ++;
|
||
if (!isset($type2Unique[$key][$value['agent']])) {
|
||
$type2Unique[$key][$value['agent']] = 1;
|
||
$type2List[$key] ++;
|
||
}
|
||
if (!isset($type3Unique[$key][$value['ip']])) {
|
||
$type3Unique[$key][$value['ip']] = 1;
|
||
$type3List[$key] ++;
|
||
}
|
||
}
|
||
|
||
$returnData['pv_list'] = array_values($type1List);
|
||
$returnData['uv_list'] = array_values($type2List);
|
||
$returnData['ip_list'] = array_values($type3List);
|
||
$returnData['time'] = array_keys($type1List);
|
||
foreach ($returnData['time'] as &$value) {
|
||
$value = (string)$value;
|
||
}
|
||
|
||
return jsonReturn(0, Lang::get('查询成功'), $returnData);
|
||
}
|
||
|
||
// 首页地区分布图
|
||
public function indexArea()
|
||
{
|
||
$websiteId = $this->request->request('website_id')?$this->request->request('website_id'):1;
|
||
$type = $this->request->request('type')?$this->request->request('type'):1;
|
||
|
||
$nowDay = date('Y-m-d');
|
||
// 今天
|
||
$startTime = strtotime($nowDay);
|
||
$endTime = strtotime(date('Y-m-d', strtotime('+1 day')));
|
||
if ($type==2) { // 昨天
|
||
$startTime = strtotime(date('Y-m-d', strtotime('-1 day')));
|
||
$endTime = strtotime($nowDay) - 1;
|
||
} elseif ($type==3) { // 最近7天
|
||
$startTime = strtotime(date('Y-m-d', strtotime('-6 day')));
|
||
$endTime = strtotime(date('Y-m-d', strtotime('+1 day')));
|
||
} elseif ($type==4) { // 最近30天
|
||
$startTime = strtotime(date('Y-m-d', strtotime('-29 day')));
|
||
$endTime = strtotime(date('Y-m-d', strtotime('+1 day')));
|
||
}
|
||
|
||
$visitModel = new VisitLog();
|
||
|
||
$list = $visitModel->where([
|
||
['create_time', '>=', $startTime],
|
||
['create_time', '<=', $endTime],
|
||
['website_id', '=', $websiteId],
|
||
['visited_area', '<>', '内网ip'],
|
||
])->select()->toArray();
|
||
|
||
$total = count($list);
|
||
$newData = [];
|
||
foreach ($list as $value) {
|
||
$areaArr = explode('-', $value['visited_area']);
|
||
$province = $areaArr[0];
|
||
if (!isset($newData[$province])) {
|
||
$newData[$province] = [
|
||
'name' => $province,
|
||
'value' => 1,
|
||
'pv_ratio' => bcmul(1 / $total, 100, 2),
|
||
];
|
||
} else {
|
||
$newData[$province]['value']++;
|
||
$newData[$province]['pv_ratio'] = bcmul($newData[$province]['value']/$total, 100, 2);
|
||
}
|
||
}
|
||
|
||
return jsonReturn(0, Lang::get('查询成功'), array_values($newData));
|
||
}
|
||
|
||
/**
|
||
* 访客年龄分布
|
||
* @return false|string|\think\response\Json
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function age()
|
||
{
|
||
$data = [
|
||
"site_id"=> $this->request->param('site_id') ? $this->request->param('site_id') : $this->site_id,
|
||
"method" => "overview/getAge"
|
||
];
|
||
$response = $this->getResponse($data);
|
||
$response = $response['body']['data']['0']['result'];
|
||
return jsonReturn(0, '查询成功', $response);
|
||
}
|
||
|
||
/**
|
||
* 今日昨日浏览量分析
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function outline(): \think\response\Json
|
||
{
|
||
$data = [
|
||
"site_id"=> $this->request->param('site_id')?$this->request->param('site_id'):$this->site_id,
|
||
"method" => "overview/getOutline"
|
||
];
|
||
$response = $this->getResponse($data);
|
||
$response = $response['body']['data']['0']['result'];
|
||
foreach ($response['items'] as $key => $value) {
|
||
if(is_numeric($value[5]) && $value[5] != '--'){
|
||
$response['items'][$key][5] = $this->secToTime($value[5]);
|
||
}elseif(is_array($value[5]) && $value[5]['val'] != '--'){
|
||
$response['items'][$key][5]['val'] = $this->secToTime($value[5]['val']);
|
||
}
|
||
}
|
||
return jsonReturn(0, Lang::get('查询成功'),$response);
|
||
}
|
||
|
||
/**
|
||
* 趋势图
|
||
* pv_count (浏览量PV)
|
||
* visitor_count (访客数UV)
|
||
* ip_count (IP 数)
|
||
* bounce_ratio (跳出率,%)
|
||
* avg_visit_time (平均访问时长,秒)
|
||
* trans_count (转化次数)
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function qxt()
|
||
{
|
||
$type = $this->request->request('type')?$this->request->request('type'):1;
|
||
$contrast = $this->request->request('contrast')?$this->request->request('contrast'):1;
|
||
$metrics = $this->request->request('metrics')?$this->request->request('metrics'):'pv_count';
|
||
switch ($metrics) {
|
||
case 'visitor_count':
|
||
$name = Lang::get('访客数(UV)');
|
||
break;
|
||
case 'ip_count':
|
||
$name = Lang::get('IP数');
|
||
break;
|
||
case 'bounce_ratio':
|
||
$name = Lang::get('跳出率');
|
||
break;
|
||
case 'avg_visit_time':
|
||
$name = Lang::get('平均访问时长');
|
||
break;
|
||
case 'trans_count':
|
||
$name = Lang::get('转化次数');
|
||
break;
|
||
default:
|
||
$name = Lang::get('浏览量(PV)');
|
||
break;
|
||
}
|
||
$et = date('Ymd', time());
|
||
if($type==1){
|
||
$st = date('Ymd', time());
|
||
if($contrast==1){
|
||
$start_date2 = date('Ymd', time()-(3600*24));
|
||
$end_date2 = date('Ymd', time()-(3600*24));
|
||
}elseif($contrast==2){
|
||
$start_date2 = date('Ymd', time()-(3600*24*7));
|
||
$end_date2 = date('Ymd', time()-(3600*24*7));
|
||
}
|
||
}elseif ($type==2) {
|
||
$st = date('Ymd', strtotime('-1 day'));
|
||
$et = date('Ymd', strtotime('-1 day'));
|
||
if($contrast==1){
|
||
$start_date2 = date('Ymd', strtotime('-1 day')-(3600*24));
|
||
$end_date2 = date('Ymd', strtotime('-1 day')-(3600*24));
|
||
}elseif($contrast==2){
|
||
$start_date2 = date('Ymd', time()-(3600*24*7));
|
||
$end_date2 = date('Ymd', time()-(3600*24*7));
|
||
}
|
||
}elseif ($type==3) {
|
||
$st = date('Ymd', strtotime('-6 day'));
|
||
}elseif ($type==4) {
|
||
$st = date('Ymd', strtotime('-29 day'));
|
||
}
|
||
if($contrast && ($type == 1 or $type == 2)){
|
||
$data = [
|
||
"site_id"=> $this->request->param('site_id')?$this->request->param('site_id'):$this->site_id,
|
||
"start_date" => $st,
|
||
"end_date" => $et,
|
||
"start_date2" => $start_date2,
|
||
"end_date2" => $end_date2,
|
||
"metrics" => $metrics,
|
||
"method" => "overview/getTimeTrendRpt"
|
||
];
|
||
}else{
|
||
$data = [
|
||
"site_id"=> $this->request->param('site_id')?$this->request->param('site_id'):$this->site_id,
|
||
"start_date" => $st,
|
||
"end_date" => $et,
|
||
"metrics" => $metrics,
|
||
"method" => "overview/getTimeTrendRpt"
|
||
];
|
||
}
|
||
$response = $this->getResponse($data);
|
||
$result = $response['body']['data']['0']['result']['items'];
|
||
|
||
$new = [];
|
||
$new[0] = $result[1];
|
||
$new[1] = $result[2];
|
||
if($metrics != 'avg_visit_time'){
|
||
foreach ($new as $key => $value) {
|
||
foreach ($value as $k => $v) {
|
||
$count = count($value);
|
||
if($type == 3 || $type == 4){
|
||
$new[$key][$k][0] = date('Y/m/d', strtotime('-'.($count-$k-1).' day'));
|
||
$new[$key][$k][1] = $v[0];
|
||
}
|
||
if($k<=10){
|
||
array_push($new[$key][$k], $k.':00-'.$k.':59');
|
||
}else{
|
||
array_push($new[$key][$k], $k.':00-'.$k.':59');
|
||
}
|
||
}
|
||
}
|
||
}else{
|
||
if($type == 3 || $type ==4){
|
||
$anew = [];
|
||
$anew[0] = $result[1];
|
||
foreach ($anew as $key => $value) {
|
||
foreach ($value as $k => $v) {
|
||
$count = count($value);
|
||
$anew[$key][$k][0] = date('Y/m/d', strtotime('-'.($count-$k-1).' day'));
|
||
$anew[$key][$k][1] = $v[0];
|
||
if($k<=10){
|
||
array_push($anew[$key][$k], $k.':00-'.$k.':59');
|
||
}else{
|
||
array_push($anew[$key][$k], $k.':00-'.$k.':59');
|
||
}
|
||
array_push($anew[$key][$k],$this->secToTime($v[0]));
|
||
}
|
||
}
|
||
return json_encode(['code'=>0, 'msg'=> Lang::get('查询成功'),'name'=>$name,'data'=>$anew]);
|
||
}else{
|
||
foreach ($new as $key => $value) {
|
||
foreach ($value as $k => $v) {
|
||
if($k<=10){
|
||
array_push($new[$key][$k], $k.':00-'.$k.':59');
|
||
}else{
|
||
array_push($new[$key][$k], $k.':00-'.$k.':59');
|
||
}
|
||
array_push($new[$key][$k],$this->secToTime($v[1]));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return jsonReturn(0, Lang::get('查询成功'),['name'=>$name,'data'=>$new]);
|
||
}
|
||
|
||
// /**
|
||
// * 关键词消费排名
|
||
// * @throws BadSysSettingException
|
||
// */
|
||
// public function search_word()
|
||
// {
|
||
// $type = $this->request->request('type')?$this->request->request('type'):1;
|
||
// $se = $this->getSTAndET($type);
|
||
// $data = [
|
||
// "site_id"=> $this->request->param('site_id')?$this->request->param('site_id'):$this->site_id,
|
||
// "start_date" => $se['st'],
|
||
// "end_date" => $se['st'],
|
||
// "metrics" => "pv_count,visit_count,visitor_count",
|
||
// "method" => "overview/getWord"
|
||
// ];
|
||
// $response = $this->getResponse($data);
|
||
// $response = $response['body']['data']['0']['result'];
|
||
// return jsonReturn(0, '查询成功',$response);
|
||
// }
|
||
|
||
/**
|
||
* Top10搜索词
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function search_word()
|
||
{
|
||
$type = $this->request->request('type')?$this->request->request('type'):1;
|
||
$se = $this->getSTAndET($type);
|
||
$data = [
|
||
"site_id"=> $this->request->param('site_id')?$this->request->param('site_id'):$this->site_id,
|
||
"start_date" => $se['st'],
|
||
"end_date" => $se['st'],
|
||
"metrics" => "pv_count,pv_ratio",
|
||
"method" => "source/searchword/a"
|
||
];
|
||
$response = $this->getResponse($data);
|
||
$response = $response['body']['data']['0']['result'];
|
||
|
||
$list = $response['items'][0] ?? [];
|
||
|
||
if (count($list) > 10) {
|
||
$list = array_slice($list, 0, 10);
|
||
$response['items'][0] = $list;
|
||
}
|
||
return jsonReturn(0, Lang::get('查询成功'),$response);
|
||
}
|
||
|
||
|
||
|
||
public function https_request($url,$data)
|
||
{
|
||
// 初始化
|
||
$curl = curl_init();
|
||
// 设置
|
||
curl_setopt($curl,CURLOPT_URL,$url);
|
||
// 检查ssl证书
|
||
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,FALSE);
|
||
// 从检查本地证书检查是否ssl加密
|
||
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,$url);
|
||
// 判断$data 判断是否post
|
||
if ( !empty($data) ) {
|
||
curl_setopt($curl,CURLOPT_POST,1);// 开启post
|
||
curl_setopt($curl,CURLOPT_POSTFIELDS,$data);// 发送post $data
|
||
}
|
||
// 返回结果 是文件流的方式返回
|
||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||
$response = curl_exec($curl);
|
||
$err = curl_error($curl);
|
||
curl_close($curl);
|
||
if($err){
|
||
return false;
|
||
}else{
|
||
return $response;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 网站概况(来源网站、搜索词、入口页面、受访页面、新老访客)
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function get_common_track_rpt(): \think\response\Json
|
||
{
|
||
$type = $this->request->request('type') ? $this->request->request('type') : 1;
|
||
$se = $this->getSTAndET($type);
|
||
$data = [
|
||
"site_id"=> $this->request->param('site_id')?$this->request->param('site_id'):$this->site_id,
|
||
"start_date" => $se['st'],
|
||
"end_date" => $se['et'],
|
||
"method" => "overview/getCommonTrackRpt"
|
||
];
|
||
$response = $this->getResponse($data);
|
||
$response = $response['body']['data']['0']['result'];
|
||
foreach ($response['visitType'] as $key => $value) {
|
||
$response['visitType'][$key]['avg_visit_time'] = $this->secToTime($value['avg_visit_time']);
|
||
}
|
||
return jsonReturn(0, Lang::get('查询成功'), $response);
|
||
}
|
||
|
||
/**
|
||
* 网站概况(地域分布)
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function area()
|
||
{
|
||
$type = $this->request->request('type')?$this->request->request('type'):2;
|
||
$se = $this->getSTAndET($type);
|
||
$data = [
|
||
"site_id"=> $this->request->param('site_id')?$this->request->param('site_id'):$this->site_id,
|
||
"start_date" => $se['st'],
|
||
"end_date" => $se['et'],
|
||
"metrics"=> "pv_count,pv_ratio",
|
||
"method" => "visit/district/a"
|
||
];
|
||
$response = $this->getResponse($data);
|
||
$response = $response['body']['data']['0']['result'];
|
||
$new = [];
|
||
foreach ($response['items'][0] as $key => $value) {
|
||
$new[$key]['name'] = $value[0]['name'];
|
||
$new[$key]['area'] = $value[0]['area'];
|
||
}
|
||
foreach ($response['items'][1] as $key => $value) {
|
||
$new[$key]['pv_count'] = $value[0];
|
||
$new[$key]['pv_ratio'] = $value[1];
|
||
}
|
||
return jsonReturn(0, Lang::get('查询成功'),$new);
|
||
}
|
||
|
||
/**
|
||
*
|
||
* 网站概况(地域分布Top10)
|
||
*
|
||
* @throws BadSysSettingException
|
||
*/
|
||
public function area_top(): \think\response\Json
|
||
{
|
||
$type = $this->request->request('type')?$this->request->request('type'):2;
|
||
$se = $this->getSTAndET($type);
|
||
$data = [
|
||
"site_id"=> $this->request->param('site_id')?$this->request->param('site_id'):$this->site_id,
|
||
"start_date" => $se['st'],
|
||
"end_date" => $se['et'],
|
||
"metrics"=> "pv_count,pv_ratio",
|
||
"method" => "visit/district/a"
|
||
];
|
||
|
||
$response = $this->getResponse($data);
|
||
$response = $response['body']['data']['0']['result'];
|
||
$new = [];
|
||
foreach ($response['items'][0] as $key => $value) {
|
||
$new[$key]['name'] = $value[0]['name'];
|
||
$new[$key]['area'] = $value[0]['area'];
|
||
}
|
||
foreach ($response['items'][1] as $key => $value) {
|
||
$new[$key]['pv_count'] = $value[0];
|
||
$new[$key]['pv_ratio'] = $value[1];
|
||
}
|
||
$new = array_slice($new, 0, 10);
|
||
return jsonReturn(0, Lang::get('查询成功'), $new);
|
||
}
|
||
|
||
public function http_request($url,$data)
|
||
{
|
||
// 初始化
|
||
$curl = curl_init();
|
||
// 设置
|
||
curl_setopt($curl,CURLOPT_URL,$url);
|
||
// 检查ssl证书
|
||
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,FALSE);
|
||
// 从检查本地证书检查是否ssl加密
|
||
curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,$url);
|
||
// 判断$data 判断是否post
|
||
if ( !empty($data) ) {
|
||
curl_setopt($curl,CURLOPT_POST,1);// 开启post
|
||
curl_setopt($curl,CURLOPT_POSTFIELDS,$data);// 发送post $data
|
||
}
|
||
// 返回结果 是文件流的方式返回
|
||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||
$response = curl_exec($curl);
|
||
|
||
$err = curl_error($curl);
|
||
curl_close($curl);
|
||
return $response;
|
||
}
|
||
|
||
// 获取开始日期和结束日期
|
||
public function getSTAndET($type): array
|
||
{
|
||
$et = date('Ymd', time());
|
||
if($type==1){
|
||
$st = date('Ymd', time());
|
||
}elseif ($type==2) {
|
||
$st = date('Ymd', strtotime('-1 day'));
|
||
$et = date('Ymd', strtotime('-1 day'));
|
||
}elseif ($type==3) {
|
||
$st = date('Ymd', strtotime('-6 day'));
|
||
}else {
|
||
$st = date('Ymd', strtotime('-29 day'));
|
||
}
|
||
return ['st' => $st,'et'=>$et];
|
||
}
|
||
|
||
public function secToTime($sec)
|
||
{
|
||
|
||
if (is_numeric($sec)) {
|
||
$strSecond = gmstrftime('%H:%M:%S', $sec);
|
||
} else {
|
||
$strSecond = $sec;
|
||
}
|
||
|
||
return $strSecond;
|
||
}
|
||
|
||
|
||
}
|