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

618 lines
21 KiB
PHP
Raw Normal View History

2025-02-13 08:21:56 +00:00
<?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;
}
}