作者 李美松

新增网站流量统计

<?php
namespace App\Console\Commands\Domain;
namespace App\Console\Commands\Bside\Domain;
use App\Exceptions\AsideGlobalException;
use App\Exceptions\BsideGlobalException;
use App\Helper\AyrShare as AyrShareHelper;
use App\Http\Logic\Aside\Domain\DomainInfoLogic;
use App\Models\AyrShare\AyrRelease as AyrReleaseModel;
use Carbon\Carbon;
use App\Models\AyrShare\AyrShare as AyrShareModel;
use Illuminate\Console\Command;
class DomainTime extends Command
... ...
<?php
namespace App\Console\Commands\Bside\Statistics;
use App\Models\Bside\Statistics\TrafficStatistics;
use App\Models\CustomerVisit\CustomerVisit;
use Illuminate\Console\Command;
class StatisticsTrend extends Command
{
public $error = 0;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'statistics_trend';
/**
* The console command description.
*
* @var string
*/
protected $description = '统计当天流量趋势数据PV|IP数量';
/**
* @name :(定时执行)handle
* @author :lyh
* @method :post
* @time :2023/5/12 14:48
*/
public function handle()
{
echo $this->statistics_trend();
}
/**
* 统计当天流量趋势数据PV|IP数量
* @return int|mixed
*/
protected function statistics_trend()
{
$customerVisit = new CustomerVisit();
$date = date('Y-m-d');
$ip_count = $customerVisit->getDayIPCount();
$pv_count = $customerVisit->getDayPVCount();
$trafficStatistics = new TrafficStatistics();
$trafficStatistics->type = TrafficStatistics::TYPE_TREND;
$trafficStatistics->
$data = [
'date' => $date,
'ip_count' => $ip_count,
'pv_count' => $pv_count,
];
// $res = $customerVisit->insert($data);
if ($res) {
$this->info('统计当天流量趋势数据PV|IP数量成功');
} else {
$this->error++;
$this->info('统计当天流量趋势数据PV|IP数量失败');
}
return $this->error;
}
}
... ...
<?php
namespace App\Http\Controllers\Bside;
use App\Models\CustomerVisit\CustomerVisit;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\JsonResponse;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
/**
* 流量统计
* Class StatisticsController
* @package App\Http\Controllers\Bside
*/
class StatisticsController extends BaseController
{
private $customerVisit;
public function __construct()
{
$this->customerVisit = new CustomerVisit();
}
/**
* 访问来源
* @return JsonResponse
*/
public function source()
{
$pv_count = $this->customerVisit->getMonthPVCount();
$ip_count = $this->customerVisit->getMonthIPCount();
$lists = $this->customerVisit->getUrlCount();
return $this->success(compact('pv_count', 'ip_count', 'lists'));
}
/**
* 地域分布
* @return JsonResponse
*/
public function distribution()
{
$pv_count = $this->customerVisit->getMonthPVCount();
$ip_count = $this->customerVisit->getMonthIPCount();
$lists = $this->customerVisit->getCountryCount();
return $this->success(compact('pv_count', 'ip_count', 'lists'));
}
/**
* 受访页面
* @return JsonResponse
*/
public function page()
{
$pv_count = $this->customerVisit->getMonthPVCount();
$ip_count = $this->customerVisit->getMonthIPCount();
$lists = $this->customerVisit->getPageCount();
return $this->success(compact('pv_count', 'ip_count', 'lists'));
}
/**
* 访问终端
* @return JsonResponse
*/
public function terminal()
{
$pv_count = $this->customerVisit->getMonthPVCount();
$ip_count = $this->customerVisit->getMonthIPCount();
$pc_count = $this->customerVisit->getTerminalPcCount();
$mobile_count = $this->customerVisit->getTerminalMobileCount();
$lists = $this->customerVisit->getCountryCount();
return $this->success(compact('pv_count', 'ip_count', 'pc_count', 'mobile_count', 'lists'));
}
/**
* 流量趋势
* @return JsonResponse
* @throws ContainerExceptionInterface
* @throws GuzzleException
* @throws NotFoundExceptionInterface
*/
public function trend()
{
// dd($this->customerVisit->getDayIPCount());
$pv_count = $this->customerVisit->getMonthPVCount();
$ip_count = $this->customerVisit->getMonthIPCount();
$inquiry = $this->getCache('inquiry_information');
$inquiry_count = $inquiry['count'] ?? 0;
$lists = $inquiry['lists'] ?? [];
return $this->success(compact('pv_count', 'ip_count', 'inquiry_count', 'lists'));
}
/**
* 获取缓存
* @param string $key 缓存键名
* @param float|int $time 缓存时间,默认2小时
* @return mixed
* @throws ContainerExceptionInterface
* @throws GuzzleException
* @throws NotFoundExceptionInterface
*/
public function getCache(string $key, $time = 60 * 60 * 2)
{
$domain = request()->getHttpHost(); //'www.wowstainless.com';
$sta_date = date('Y-m-01');
$key = $key . '_' . $this->stringUnderlineLowercase($domain) . '_' . str_replace('-', '_', $sta_date);
$value = cache()->get($key);
if (!$value) {
$value = $this->getInquiryInformation($domain, $sta_date);
cache()->put($key, $value, $time);
}
return $value;
}
/**
* 正则 - 名字转为小写并将空格转为下划线
* @param $name
* @return string
*/
public function stringUnderlineLowercase($name)
{
return trim(strtolower(preg_replace('/[^a-zA-Z0-9]/', '_', $name)));
}
/**
* 获取第三方询盘信息
* @return array|string
* @throws GuzzleException
*/
public function getInquiryInformation($domain, $sta_date)
{
$token = md5($domain . date("Y-m-d"));
$source = '1,3';
$url = "https://form.globalso.com/api/external-interface/country_con/15243d63ed5a5738?domain={$domain}&token={$token}&source={$source}&sta_date={$sta_date}";
$client = new Client(['verify' => false]);
$http = $client->get($url);
$data = [];
if ($http->getStatusCode() != 200) {
return $data;
}
$content = $http->getBody()->getContents();
$json = json_decode($content, true);
if ($json['status'] != 200) {
return $content;
}
$data['count'] = $json['data']['count'];
$data['lists'] = $json['data']['data'];
return $data;
}
}
... ...
... ... @@ -10,6 +10,8 @@ use App\Http\Logic\Aside\BaseLogic;
use App\Http\Logic\Aside\Devops\ServerInformationLogic;
use App\Models\Aside\Domain\DomainInfo;
use App\Models\Aside\Domain\DomainInfoLog;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
... ... @@ -74,7 +76,7 @@ class DomainInfoLogic extends BaseLogic
$request = $this->param;
$this->extracted($request, $domain, $original);
// 检查ip是否存在
if(array_key_exists('domain', $request)){
if (array_key_exists('domain', $request)) {
if ($domain->domain != $request['domain']) {
if ($this->checkDomain($request['domain'])) {
$this->fail('域名信息修改失败,域名已存在', Code::USER_ERROR);
... ... @@ -254,15 +256,23 @@ class DomainInfoLogic extends BaseLogic
/**
* 域名到期时间
* @param $domain
* @return array
* @throws GuzzleException
*/
public function getDomainTime($domain)
{
$conJson = file_get_contents("http://openai.waimaoq.com/v1/whois_api?domain={$domain}");
$conArr = json_decode($conJson, true);
$url = "http://openai.waimaoq.com/v1/whois_api?domain={$domain}";
$client = new Client(['verify' => false]);
$http = $client->get($url);
$data = [];
if ($conArr['code'] == 200) {
$con = $conArr['text'];
if ($http->getStatusCode() != 200) {
return $data;
}
$content = $http->getBody()->getContents();
$json = json_decode($content, true);
if ($json['code'] == 200) {
$con = $json['text'];
$data['domain'] = $domain;
$data['validFrom'] = $con['creation_date'];
$data['validTo'] = $con['expiration_date'];
... ...
<?php
namespace App\Models\Bside\Statistics;
use App\Models\Base;
/**
* 流量统计
*/
class TrafficStatistics extends Base
{
protected $table = 'gl_traffic_statistics';
/** @var int 访问来源 */
const TYPE_SOURCE = 1;
/** @var int 地域分布 */
const TYPE_DISTRIBUTION = 2;
/** @var int 受访页面 */
const TYPE_PAGE = 3;
/** @var int 访问终端 */
const TYPE_TERMINAL = 4;
/** @var int 流量趋势 */
const TYPE_TREND = 5;
}
... ...
<?php
namespace App\Models\Bside\Statistics;
use App\Models\Base;
/**
* 流量统计
*/
class TrafficTrends extends Base
{
protected $table = 'gl_traffic_trends';
}
... ...
... ... @@ -3,8 +3,156 @@
namespace App\Models\CustomerVisit;
use App\Models\Base;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class CustomerVisit extends Base
{
use HasFactory;
protected $table = 'gl_customer_visit';
const LIMIT = 15;
/** @var int PC端 */
const TERMINAL_PC = 1;
/** @var int 移动端 */
const TERMINAL_MOBILE = 2;
public function queryField($field, $action = 'count', $whereDay = false)
{
$query = $this->query()
->selectRaw("{$action}({$field}) as count")
->whereYear('updated_date', '=', date("Y"))
->whereMonth('updated_date', '=', date("m"));
if ($whereDay) {
$query->whereDay('updated_date', '=', date("d"));
}
return (int)$query->value('count') ?? 0;
}
public function queryTerminal($field, $action = self::TERMINAL_PC)
{
return (int)$this->query()
->selectRaw("count(*) as count")
->where($field, '=', $action)
->whereYear('updated_date', '=', date("Y"))
->whereMonth('updated_date', '=', date("m"))
->value('count') ?? 0;
}
public function getRankingData($field, $limit = self::LIMIT)
{
return $this->query()
->selectRaw('count(*) as count, ' . $field . ' as request')
->whereYear('updated_date', '=', date("Y"))
->whereMonth('updated_date', '=', date("m"))
->groupBy($field)
->orderBy('count', 'desc')
->limit($limit)
->get();
}
public function getSum($field)
{
return $this->queryField($field, 'sum');
}
public function getCount($field)
{
return $this->queryField($field);
}
public function returnLists(Collection $data, int $limit = self::LIMIT)
{
$lists = $data->toArray();
$lists = $lists ? array_slice($lists, 0, $limit) : [];
$count = $data->count();
return compact('lists', 'count');
}
/**
* 查询当月流量的浏览量
* @return int
*/
public function getMonthPVCount()
{
return $this->getSum('depth');
}
/**
* 查询当月流量的访客量
* @return int
*/
public function getMonthIPCount()
{
return $this->getCount('ip');
}
/**
* 查询当月TOP15访问来源
* @param int $limit
* @return array
*/
public function getUrlCount(int $limit = self::LIMIT)
{
return $this->getRankingData('referrer_url', $limit);
}
/**
* 查询当月TOP15访问国家来源
* @param int $limit
* @return array
*/
public function getCountryCount(int $limit = self::LIMIT)
{
return $this->getRankingData('country', $limit);
}
/**
* 查询当月TOP15受访页面
* @param int $limit
* @return array
*/
public function getPageCount(int $limit = self::LIMIT)
{
return $this->getRankingData('url', $limit);
}
/**
* 查询当月TOP15访问终端
* @return int
*/
public function getTerminalPcCount()
{
return $this->queryTerminal('device_port');
}
/**
* 查询当月TOP15访问终端
* @return int
*/
public function getTerminalMobileCount()
{
return $this->queryTerminal('device_port', self::TERMINAL_MOBILE);
}
/**
* 查询当日流量的浏览量
* @return int
*/
public function getDayPVCount()
{
return $this->queryField('depth', 'sum', true);
}
/**
* 查询当日流量的访客量
* @return int
*/
public function getDayIPCount()
{
return $this->queryField('ip', 'count', true);
}
}
... ...
... ... @@ -19,6 +19,7 @@
"mrgoon/aliyun-sms": "^2.0"
},
"require-dev": {
"barryvdh/laravel-ide-helper": "^2.13",
"facade/ignition": "^2.5",
"fakerphp/faker": "^1.9.1",
"laravel/sail": "^1.0.1",
... ...
... ... @@ -106,7 +106,7 @@ return [
|
*/
'faker_locale' => 'en_US',
'faker_locale' => 'zh_CN',
/*
|--------------------------------------------------------------------------
... ...
... ... @@ -5,6 +5,14 @@
use Illuminate\Support\Facades\Route;
Route::prefix('stat')->group(function () {
Route::get('/source', [\App\Http\Controllers\Bside\StatisticsController::class, 'source'])->name('stat_source');
Route::get('/distribution', [\App\Http\Controllers\Bside\StatisticsController::class, 'distribution'])->name('stat_distribution');
Route::get('/page', [\App\Http\Controllers\Bside\StatisticsController::class, 'page'])->name('stat_page');
Route::get('/terminal', [\App\Http\Controllers\Bside\StatisticsController::class, 'terminal'])->name('stat_terminal');
Route::get('/trend', [\App\Http\Controllers\Bside\StatisticsController::class, 'trend'])->name('stat_trend');
});
//必须登录验证的路由组
Route::middleware(['bloginauth'])->group(function () {
//登录用户编辑个人资料
... ... @@ -242,20 +250,19 @@ Route::middleware(['bloginauth'])->group(function () {
Route::post('/chunk/create', [\App\Http\Controllers\Aside\TemplateController::class, 'chunk_save'])->name('admin.template.chunk_create');
Route::post('/chunk/update', [\App\Http\Controllers\Aside\TemplateController::class, 'chunk_save'])->name('admin.template.chunk_update');
Route::delete('/chunk/delete/{chunk_id}', [\App\Http\Controllers\Aside\TemplateController::class, 'chunk_delete'])->where('chunk_id','\d+')->name('admin.template.chunk_delete');
Route::delete('/chunk/delete/{chunk_id}', [\App\Http\Controllers\Aside\TemplateController::class, 'chunk_delete'])->where('chunk_id', '\d+')->name('admin.template.chunk_delete');
});
// 自定义页面,专题页
Route::prefix('custom')->group(function () {
Route::get('/', [\App\Http\Controllers\Bside\CustomController::class, 'index'])->name('bside_custom');
Route::post('/create', [\App\Http\Controllers\Bside\CustomController::class, 'save'])->name('bside_custom_create');
Route::post('/update', [\App\Http\Controllers\Bside\CustomController::class, 'save'])->name('bside_custom_update');
Route::delete('/delete', [\App\Http\Controllers\Bside\CustomController::class, 'delete'])->name('bside_custom_delete');
Route::any('/html/{id}', [\App\Http\Controllers\Bside\CustomController::class, 'html'])->where('id','\d+')->name('bside_custom_delete');
Route::any('/html/{id}', [\App\Http\Controllers\Bside\CustomController::class, 'html'])->where('id', '\d+')->name('bside_custom_delete');
});
// 导航栏编辑
... ... @@ -295,6 +302,6 @@ Route::group([], function () {
Route::any('/login', [\App\Http\Controllers\Bside\ComController::class, 'login'])->name('login');
Route::any('/sendLoginSms', [\App\Http\Controllers\Bside\ComController::class, 'sendLoginSms'])->name('sendLoginSms');
Route::get('/file/download', [\App\Http\Controllers\Bside\FileController::class, 'download'])->name('file_download');
Route::any('/image/{hash}/{w?}/{h?}', [\App\Http\Controllers\File\ImageController::class,'index'])->name('image_show');
Route::any('/file_hash/{hash}', [\App\Http\Controllers\File\FileController::class,'index'])->name('file_show');
Route::any('/image/{hash}/{w?}/{h?}', [\App\Http\Controllers\File\ImageController::class, 'index'])->name('image_show');
Route::any('/file_hash/{hash}', [\App\Http\Controllers\File\FileController::class, 'index'])->name('file_show');
});
... ...