init: 项目初始代码

This commit is contained in:
2026-10-14 14:00:29 +08:00
commit cc434cf89f
464 changed files with 66984 additions and 0 deletions

View File

@@ -0,0 +1,249 @@
<?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);
}
}