cms-manage/app/controller/backend/StatisticsController.php

618 lines
21 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}