修复代码增加统计,增加redis
This commit is contained in:
@@ -6,7 +6,8 @@ namespace app\index\controller;
|
||||
use think\App;
|
||||
use think\facade\View;
|
||||
use think\facade\Request;
|
||||
use think\facade\Config;
|
||||
use think\facade\Db;
|
||||
use app\service\VisitStatsService;
|
||||
|
||||
/**
|
||||
* 前台控制器基础类
|
||||
@@ -18,6 +19,7 @@ abstract class BaseController
|
||||
* @var \think\Request
|
||||
*/
|
||||
protected $request;
|
||||
protected $visitStats;
|
||||
|
||||
/**
|
||||
* 应用实例
|
||||
@@ -34,6 +36,7 @@ abstract class BaseController
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
$this->visitStats = new VisitStatsService();
|
||||
|
||||
// 控制器初始化
|
||||
$this->initialize();
|
||||
@@ -44,20 +47,25 @@ abstract class BaseController
|
||||
*/
|
||||
protected function initialize()
|
||||
{
|
||||
// 记录访问
|
||||
$this->visitStats->recordVisit($this->getControllerName());
|
||||
|
||||
// 获取配置
|
||||
$configList = Db::table('yz_admin_config')
|
||||
->where('config_status', 1)
|
||||
->order('config_sort DESC')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 将配置数据转换为键值对形式
|
||||
$config = [];
|
||||
foreach ($configList as $item) {
|
||||
$config[$item['config_name']] = $item['config_value'];
|
||||
}
|
||||
|
||||
// 设置通用变量
|
||||
View::assign([
|
||||
'site_name' => '网站名称',
|
||||
'site_description' => '网站描述',
|
||||
'site_keywords' => '网站关键词',
|
||||
'config' => [
|
||||
'admin_name' => Config::get('site.name', '云泽科技'),
|
||||
'admin_phone' => Config::get('site.phone', '400-123-4567'),
|
||||
'admin_email' => Config::get('site.email', 'admin@example.com'),
|
||||
'admin_wechat' => Config::get('site.wechat_qrcode', '/static/images/wechat_qrcode.jpg'),
|
||||
'logo' => Config::get('site.logo', '/static/images/logo.png'),
|
||||
'logo1' => Config::get('site.logo1', '/static/images/logo1.png'),
|
||||
'admin_route' => Config::get('site.admin_route', '/admin/')
|
||||
]
|
||||
'config' => $config
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace app\service;
|
||||
use think\facade\Cache;
|
||||
use think\facade\Request;
|
||||
use think\facade\Db;
|
||||
use think\facade\Log;
|
||||
|
||||
class VisitStatsService
|
||||
{
|
||||
@@ -15,8 +16,14 @@ class VisitStatsService
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// 获取Redis处理器
|
||||
$this->redis = Cache::store('redis')->handler();
|
||||
try {
|
||||
// 获取Redis处理器
|
||||
$this->redis = Cache::store('redis')->handler();
|
||||
} catch (\Exception $e) {
|
||||
// Redis连接失败,使用文件缓存
|
||||
$this->redis = Cache::store('file')->handler();
|
||||
Log::error('Redis连接失败,已切换到文件缓存:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24,45 +31,56 @@ class VisitStatsService
|
||||
*/
|
||||
public function recordVisit(string $page = 'home', string $userId = null): array
|
||||
{
|
||||
$date = date('Y-m-d');
|
||||
$hour = date('H');
|
||||
$userId = $userId ?? Request::ip();
|
||||
|
||||
// 使用管道提高性能
|
||||
$pipe = $this->redis->multi();
|
||||
|
||||
// 总访问量(PV)
|
||||
$pipe->incr($this->prefix.'total_visits');
|
||||
|
||||
// 每日访问量
|
||||
$pipe->incr($this->prefix.'daily:'.$date);
|
||||
|
||||
// 页面统计
|
||||
$pipe->zIncrBy($this->prefix.'page_views', 1, $page);
|
||||
|
||||
// UV统计(使用HyperLogLog节省内存)
|
||||
$pipe->pfAdd($this->prefix.'uv:'.$date, [$userId]);
|
||||
|
||||
// 时段统计
|
||||
$pipe->hIncrBy($this->prefix.'hourly:'.$date, $hour, 1);
|
||||
|
||||
// 执行所有命令
|
||||
$result = $pipe->exec();
|
||||
|
||||
// 更新数据库统计
|
||||
$this->updateDailyStats($date, [
|
||||
'total_visits' => $result[0],
|
||||
'daily_visits' => $result[1],
|
||||
'unique_visitors' => $this->getUniqueVisitors($date)
|
||||
]);
|
||||
|
||||
return [
|
||||
'total' => $result[0],
|
||||
'daily' => $result[1],
|
||||
'page' => $result[2],
|
||||
'uv' => $result[3],
|
||||
'hourly'=> $result[4]
|
||||
];
|
||||
try {
|
||||
$date = date('Y-m-d');
|
||||
$hour = date('H');
|
||||
$userId = $userId ?? Request::ip();
|
||||
|
||||
// 使用管道提高性能
|
||||
$pipe = $this->redis->multi();
|
||||
|
||||
// 总访问量(PV)
|
||||
$pipe->incr($this->prefix.'total_visits');
|
||||
|
||||
// 每日访问量
|
||||
$pipe->incr($this->prefix.'daily:'.$date);
|
||||
|
||||
// 页面统计
|
||||
$pipe->zIncrBy($this->prefix.'page_views', 1, $page);
|
||||
|
||||
// UV统计(使用HyperLogLog节省内存)
|
||||
$pipe->pfAdd($this->prefix.'uv:'.$date, [$userId]);
|
||||
|
||||
// 时段统计
|
||||
$pipe->hIncrBy($this->prefix.'hourly:'.$date, $hour, 1);
|
||||
|
||||
// 执行所有命令
|
||||
$result = $pipe->exec();
|
||||
|
||||
// 更新数据库统计
|
||||
$this->updateDailyStats($date, [
|
||||
'total_visits' => $result[0],
|
||||
'daily_visits' => $result[1],
|
||||
'unique_visitors' => $this->getUniqueVisitors($date)
|
||||
]);
|
||||
|
||||
return [
|
||||
'total' => $result[0],
|
||||
'daily' => $result[1],
|
||||
'page' => $result[2],
|
||||
'uv' => $result[3],
|
||||
'hourly'=> $result[4]
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
Log::error('访问统计失败:' . $e->getMessage());
|
||||
return [
|
||||
'total' => 0,
|
||||
'daily' => 0,
|
||||
'page' => 0,
|
||||
'uv' => 0,
|
||||
'hourly'=> 0
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,36 +88,63 @@ class VisitStatsService
|
||||
*/
|
||||
protected function updateDailyStats(string $date, array $stats)
|
||||
{
|
||||
// 获取其他统计数据
|
||||
$otherStats = [
|
||||
'total_users' => Db::name('users')->where('delete_time', null)->count(),
|
||||
'new_users' => Db::name('users')->whereDay('create_time', $date)->count(),
|
||||
'total_articles' => Db::name('articles')->where('delete_time', null)->count(),
|
||||
'daily_articles' => Db::name('articles')->whereDay('create_time', $date)->count(),
|
||||
'article_views' => Db::name('articles')->whereDay('update_time', $date)->sum('views'),
|
||||
'total_resources' => Db::name('resources')->where('delete_time', null)->count(),
|
||||
'daily_resources' => Db::name('resources')->whereDay('create_time', $date)->count(),
|
||||
'resource_downloads' => Db::name('resources')->whereDay('update_time', $date)->sum('downloads')
|
||||
];
|
||||
|
||||
// 合并统计数据
|
||||
$stats = array_merge($stats, $otherStats);
|
||||
|
||||
// 更新或插入统计数据
|
||||
Db::name('daily_stats')->insertOrUpdate([
|
||||
'date' => $date,
|
||||
'total_users' => $stats['total_users'],
|
||||
'new_users' => $stats['new_users'],
|
||||
'total_visits' => $stats['total_visits'],
|
||||
'daily_visits' => $stats['daily_visits'],
|
||||
'unique_visitors' => $stats['unique_visitors'],
|
||||
'total_articles' => $stats['total_articles'],
|
||||
'daily_articles' => $stats['daily_articles'],
|
||||
'article_views' => $stats['article_views'],
|
||||
'total_resources' => $stats['total_resources'],
|
||||
'daily_resources' => $stats['daily_resources'],
|
||||
'resource_downloads' => $stats['resource_downloads']
|
||||
], ['date']);
|
||||
try {
|
||||
// 获取其他统计数据
|
||||
$otherStats = [
|
||||
'total_users' => Db::name('users')->count(), // 移除 delete_time 条件
|
||||
'new_users' => Db::name('users')->whereDay('create_time', $date)->count(),
|
||||
'total_articles' => Db::name('articles')->where('delete_time', null)->count(),
|
||||
'daily_articles' => Db::name('articles')->whereDay('create_time', $date)->count(),
|
||||
'article_views' => Db::name('articles')->whereDay('update_time', $date)->sum('views'),
|
||||
'total_resources' => Db::name('resources')->where('delete_time', null)->count(),
|
||||
'daily_resources' => Db::name('resources')->whereDay('create_time', $date)->count(),
|
||||
'resource_downloads' => Db::name('resources')->whereDay('update_time', $date)->sum('downloads')
|
||||
];
|
||||
|
||||
// 记录日志,方便调试
|
||||
Log::info('统计数据:' . json_encode($otherStats, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
// 合并统计数据
|
||||
$stats = array_merge($stats, $otherStats);
|
||||
|
||||
// 检查记录是否存在
|
||||
$exists = Db::name('daily_stats')->where('date', $date)->find();
|
||||
|
||||
if ($exists) {
|
||||
// 更新已存在的记录
|
||||
Db::name('daily_stats')->where('date', $date)->update([
|
||||
'total_users' => $stats['total_users'],
|
||||
'new_users' => $stats['new_users'],
|
||||
'total_visits' => $stats['total_visits'],
|
||||
'daily_visits' => $stats['daily_visits'],
|
||||
'unique_visitors' => $stats['unique_visitors'],
|
||||
'total_articles' => $stats['total_articles'],
|
||||
'daily_articles' => $stats['daily_articles'],
|
||||
'article_views' => $stats['article_views'],
|
||||
'total_resources' => $stats['total_resources'],
|
||||
'daily_resources' => $stats['daily_resources'],
|
||||
'resource_downloads' => $stats['resource_downloads']
|
||||
]);
|
||||
} else {
|
||||
// 插入新记录
|
||||
Db::name('daily_stats')->insert([
|
||||
'date' => $date,
|
||||
'total_users' => $stats['total_users'],
|
||||
'new_users' => $stats['new_users'],
|
||||
'total_visits' => $stats['total_visits'],
|
||||
'daily_visits' => $stats['daily_visits'],
|
||||
'unique_visitors' => $stats['unique_visitors'],
|
||||
'total_articles' => $stats['total_articles'],
|
||||
'daily_articles' => $stats['daily_articles'],
|
||||
'article_views' => $stats['article_views'],
|
||||
'total_resources' => $stats['total_resources'],
|
||||
'daily_resources' => $stats['daily_resources'],
|
||||
'resource_downloads' => $stats['resource_downloads']
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('更新统计数据失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +152,12 @@ class VisitStatsService
|
||||
*/
|
||||
public function getTotalVisits(): int
|
||||
{
|
||||
return (int)$this->redis->get($this->prefix.'total_visits');
|
||||
try {
|
||||
return (int)$this->redis->get($this->prefix.'total_visits');
|
||||
} catch (\Exception $e) {
|
||||
Log::error('获取总访问量失败:' . $e->getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,8 +165,13 @@ class VisitStatsService
|
||||
*/
|
||||
public function getDailyVisits(string $date = null): int
|
||||
{
|
||||
$date = $date ?? date('Y-m-d');
|
||||
return (int)$this->redis->get($this->prefix.'daily:'.$date);
|
||||
try {
|
||||
$date = $date ?? date('Y-m-d');
|
||||
return (int)$this->redis->get($this->prefix.'daily:'.$date);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('获取当日访问量失败:' . $e->getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,10 +179,13 @@ class VisitStatsService
|
||||
*/
|
||||
public function getUniqueVisitors(string $date = null): int
|
||||
{
|
||||
$date = $date ?? date('Y-m-d');
|
||||
return $this->redis->pfCount($this->prefix.'uv:'.$date);
|
||||
try {
|
||||
$date = $date ?? date('Y-m-d');
|
||||
return $this->redis->pfCount($this->prefix.'uv:'.$date);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('获取独立访客数失败:' . $e->getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取热门页面
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user