249 lines
9.2 KiB
PHP
249 lines
9.2 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
|
||
namespace app\index\controller;
|
||
|
||
use app\library\LogToKafka;
|
||
use app\BaseController;
|
||
use app\index\model\Navigator;
|
||
use app\index\model\SystemConfig;
|
||
use DeviceDetector\DeviceDetector;
|
||
use DeviceDetector\Parser\Device\AbstractDeviceParser;
|
||
use GeoIp2\Database\Reader;
|
||
use think\facade\Cache;
|
||
use think\facade\Env;
|
||
use think\facade\Lang;
|
||
use think\facade\View;
|
||
|
||
/**
|
||
* 控制器基类
|
||
*/
|
||
class Base extends BaseController
|
||
{
|
||
use LogToKafka;
|
||
/**
|
||
* 平台固定为1.不是多平台
|
||
* @var int
|
||
*/
|
||
protected $platformId = 1;
|
||
|
||
/**
|
||
* 查询条件,模糊字段与值。格式 ['name'=>'test']
|
||
* @var array
|
||
*/
|
||
protected $vague = [];
|
||
|
||
/**
|
||
* 精准查询,精确字段,格式['language_id'=> 1]
|
||
* @var array
|
||
*/
|
||
protected $focus = [];
|
||
|
||
/**
|
||
* 排序字段。格式 ['sort'=>'desc']
|
||
* @var array
|
||
*/
|
||
protected $sort = [];
|
||
|
||
/**
|
||
* 模型
|
||
* @var array
|
||
*/
|
||
protected $model = null;
|
||
|
||
/**
|
||
* 语言ID
|
||
* @var int|mixed
|
||
*/
|
||
protected $languageId = 1;
|
||
|
||
/**
|
||
* 导航栏模型
|
||
* @var null
|
||
*/
|
||
protected $navModel = null;
|
||
|
||
/**
|
||
* 系统配置模型
|
||
* @var null
|
||
*/
|
||
protected $systemConfigModel = null;
|
||
|
||
/**
|
||
* 接口监控数据
|
||
* @var string[]
|
||
*/
|
||
protected $apiLog = [
|
||
'items' => '', /*项目名称*/
|
||
'forum' => '', /*模块*/
|
||
'forum_code' => '', /*模块日志编码*/
|
||
'url' => '', /*访问页*/
|
||
'refer' => '', /*访问来源*/
|
||
'click' => '', /*点击次数*/
|
||
'content' => '', /*访问内容*/
|
||
'ip' => '', /*访客IP*/
|
||
'country' => '', /*国家*/
|
||
'province' => '', /*省*/
|
||
'city' => '', /*市*/
|
||
'start_time' => '', /*点击时间*/
|
||
'drive' => '', /*PC OR 移动端*/
|
||
'system' => '', /*设备系统*/
|
||
'brower' => '', /*浏览器*/
|
||
'models' => '', /*设备型号*/
|
||
'date_time' => '' /*生成时间*/
|
||
];
|
||
|
||
/**
|
||
* 判断请求来源是否是手机设备
|
||
* @return bool
|
||
*/
|
||
private function isMobile() : bool
|
||
{
|
||
//如果有HTTP_X_WAP_PROFILE则一定是移动设备
|
||
if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
|
||
return true;
|
||
}
|
||
//如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
|
||
if (isset($_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'], 'wap')) {
|
||
return true;
|
||
}
|
||
//野蛮方法,判断手机发送的客户端标志,兼容性有待提高
|
||
if (isset($_SERVER['HTTP_USER_AGENT'])) {
|
||
|
||
$clientKeywords = ['nokia','sony','ericsson','mot','samsung','htc','sgh','lg','sharp','sie-','philips','panasonic','alcatel','lenovo','iphone','ipod','blackberry','meizu','android','netfront','symbian','ucweb','windowsce','palm','operamini','operamobi','openwave','nexusone','cldc','midp','wap','mobile'];
|
||
|
||
//从HTTP_USER_AGENT中查找手机浏览器的关键字
|
||
if (preg_match("/(".implode('|', $clientKeywords).")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
|
||
return true;
|
||
}
|
||
}
|
||
//协议法,因为有可能不准确,放到最后判断
|
||
if (isset($_SERVER['HTTP_ACCEPT'])) {
|
||
//如果只支持wml并且不支持html那一定是移动设备
|
||
//如果支持wml和html但是wml在html之前则是移动设备
|
||
if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 初始化
|
||
* @return void
|
||
* @throws \think\db\exception\DataNotFoundException
|
||
* @throws \think\db\exception\DbException
|
||
* @throws \think\db\exception\ModelNotFoundException
|
||
*/
|
||
public function initialize()
|
||
{
|
||
$controller = $this->request->controller();
|
||
|
||
$this->languageId = $this->request->language_id??1;
|
||
//通过中间件过来的语言包,动态设置
|
||
Lang::setLangSet($this->request->language_code??'zh-cn');
|
||
//重新加载动态设置的语言包
|
||
$this->app->loadLangPack(Lang::getLangSet());
|
||
// 初始化公共模型
|
||
$this->navModel = new Navigator();
|
||
|
||
$this->systemConfigModel = new SystemConfig();
|
||
|
||
// 初始化公共页面,判断语言包
|
||
// 导航
|
||
$navInfo = $this->navModel->getNavInfo($this->languageId,$this->platformId,$controller);
|
||
$navInfo = recursion_func($navInfo);
|
||
$footerNavInfo = $this->navModel->getFootNavInfo($this->languageId,$this->platformId);
|
||
$footerNavInfo = recursion_func($footerNavInfo);
|
||
// 头部版本号
|
||
// 静态版本号
|
||
$version = Env::get('front.version');
|
||
// 尾部数据
|
||
$footerInfo = $this->systemConfigModel->getFooterInfo($this->languageId);
|
||
// 首页多网站切换
|
||
$multiLanguage = $this->systemConfigModel->getWebSiteInfo($this->languageId);
|
||
// 其他公共数据
|
||
// 增加标签显示
|
||
$metaTitle = $this->systemConfigModel->getMetaTitle($this->languageId,'common');
|
||
View::assign('meta',$metaTitle);
|
||
View::assign('nav_info',$navInfo);
|
||
View::assign('nav_footer_info',$footerNavInfo);
|
||
View::assign('footer_info',$footerInfo);
|
||
View::assign('multi_lang',$multiLanguage);
|
||
View::assign('ver',$version);
|
||
View::assign('is_dev',Env::get('APP_DEBUG'));
|
||
View::assign('is_mobile',$this->isMobile());
|
||
}
|
||
|
||
/**
|
||
* 访问日志监控,提交kafka生产者接口
|
||
* @return \think\response\Json
|
||
* @throws \GeoIp2\Exception\AddressNotFoundException
|
||
* @throws \MaxMind\Db\Reader\InvalidDatabaseException
|
||
*/
|
||
public function submitActionLog()
|
||
{
|
||
$inputData = $this->request->param();
|
||
$model = explode('//',$inputData['url']);
|
||
$model = explode('/',$model[1]);
|
||
$this->apiLog['items'] = Env::get('platform_name','官网');
|
||
$this->apiLog['forum'] = count($model) > 1 && $model[1] != '' ? $model[1] : 'index';
|
||
$this->apiLog['forum_code'] = 200;
|
||
$this->apiLog['url'] = $inputData['url'];
|
||
$this->apiLog['refer'] = $inputData['url'];
|
||
$this->apiLog['content'] = $inputData['content'];
|
||
$this->apiLog['click'] = $inputData['click'];
|
||
$this->apiLog['start_time'] = date('Y-m-d H:i:s',(int)ceil(($inputData['date_time'] - (int)ceil((int)$inputData['start_time'])) / 1000) );
|
||
$this->apiLog['date_time'] = date('Y-m-d H:i:s',(int)ceil($inputData['date_time'] / 1000) );
|
||
//获取应用启动时间
|
||
//获取访问设备,系统版本,浏览器,设备型号
|
||
$userAgent = $inputData['drive'];
|
||
AbstractDeviceParser::setVersionTruncation(AbstractDeviceParser::VERSION_TRUNCATION_NONE);
|
||
$dd = new DeviceDetector($userAgent);
|
||
$dd->parse();
|
||
|
||
if ($dd->isBot()) {
|
||
$this->apiLog['brower'] = '未知';
|
||
$this->apiLog['system'] = '未知';
|
||
$this->apiLog['drive'] = '未知';
|
||
$this->apiLog['models'] = '爬虫';
|
||
} else {
|
||
$clientInfo = $dd->getClient();
|
||
$osInfo = $dd->getOs();
|
||
$device = $dd->getDeviceName();
|
||
$brand = $dd->getBrandName();
|
||
$model = $dd->getModel();
|
||
$this->apiLog['brower'] = !empty($clientInfo) ? $clientInfo['name'].' '.$clientInfo['version'] : '未知';
|
||
$this->apiLog['system'] = !empty($osInfo) ? $osInfo['name'].' '.$osInfo['version'] : '未知';
|
||
$this->apiLog['models'] = $device . " " . $brand . " ". $model;
|
||
$this->apiLog['drive'] = $device;
|
||
}
|
||
//解析IP地址,得到国家,城市,地址,
|
||
$this->apiLog['ip'] = $inputData['ip'];
|
||
|
||
if (!filter_var($inputData['ip'],FILTER_VALIDATE_IP,FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE | FILTER_NULL_ON_FAILURE)) {
|
||
$this->apiLog['country'] = '本地';
|
||
$this->apiLog['province'] = '本地';
|
||
$this->apiLog['city'] = '本地';
|
||
} else {
|
||
$readerCity = new Reader(public_path() . 'GeoLite2-City.mmdb');
|
||
$record = $readerCity->city($inputData['ip']);
|
||
$country = $record->country->names['zh-CN'];
|
||
$province = $record->subdivisions[0]->names['zh-CN']??'';
|
||
$city = $record->city->names['zh-CN']??$record->city->names['en'];
|
||
$china = ['香港','澳门','台湾'];
|
||
if (in_array($country,$china)) {
|
||
$province = $city = $country;
|
||
$country = '中国';
|
||
}
|
||
|
||
$this->apiLog['country'] = $country;
|
||
$this->apiLog['province'] = $province;
|
||
$this->apiLog['city'] = $city;
|
||
}
|
||
// Cache::set('this-api-log',$this->apiLog);
|
||
// 返回信息前,写入kafka log日志
|
||
$result = $this->sendLogsToKafkaProduce($this->apiLog,'action_logs',Env::get('database.database'),'add');
|
||
return $result ? json('提交成功') : json('提交失败',504);
|
||
}
|
||
} |