chore: 重写初始提交(清空历史,整理后全量提交)
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/*
|
||||
* @Author: YwxApp <ywx@ywxapp.cn>
|
||||
* @Date: 2026-07-28 00:00:00
|
||||
* @Description: 搜索蜘蛛统计
|
||||
* @FilePath: \ywxapp_dev\app\backend\controller\Spider.php
|
||||
* @CustomString: Copyright (c) 2026 YwxApp
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace app\backend\controller;
|
||||
|
||||
use think\facade\Db;
|
||||
use ywxapp\controller\BackendBase;
|
||||
use ywxapp\library\SpiderDetect;
|
||||
|
||||
/**
|
||||
* 搜索蜘蛛统计
|
||||
*
|
||||
* 数据来源:全局中间件 ywxapp\middleware\SpiderStat 写入的
|
||||
* spider_log(明细)与 spider_stat(按日聚合)两张表。
|
||||
*
|
||||
* @author ywxapp <admin@ywxapp.cn>
|
||||
*/
|
||||
class Spider extends BackendBase
|
||||
{
|
||||
protected $noNeedLogin = [];
|
||||
protected $noNeedVerify = [];
|
||||
|
||||
/**
|
||||
* 抓取明细列表(页面 + Ajax)
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
$page = $this->request->param('page/d', 1);
|
||||
$limit = $this->request->param('limit/d', 15);
|
||||
$spider = $this->request->param('spider', '');
|
||||
$ip = $this->request->param('ip', '');
|
||||
$url = $this->request->param('url', '');
|
||||
$date = $this->request->param('date', ''); // YYYY-MM-DD
|
||||
|
||||
$query = Db::name('spider_log');
|
||||
if ($spider !== '') {
|
||||
$query->where('spider', $spider);
|
||||
}
|
||||
if ($ip !== '') {
|
||||
$query->where('ip', 'like', $ip . '%');
|
||||
}
|
||||
if ($url !== '') {
|
||||
$query->where('url', 'like', '%' . $url . '%');
|
||||
}
|
||||
if ($date !== '' && ($ts = strtotime($date)) !== false) {
|
||||
$query->whereBetween('create_at', [$ts, $ts + 86399]);
|
||||
}
|
||||
|
||||
try {
|
||||
$list = $query->order('id', 'desc')
|
||||
->paginate(['page' => $page, 'list_rows' => $limit]);
|
||||
$items = $list->items();
|
||||
$labels = SpiderDetect::labels();
|
||||
foreach ($items as &$item) {
|
||||
$item['spider_text'] = $labels[$item['spider']] ?? $item['spider'];
|
||||
$item['time_text'] = date('Y-m-d H:i:s', (int) $item['create_at']);
|
||||
}
|
||||
unset($item);
|
||||
$this->result->setCount($list->total())->success($items);
|
||||
} catch (\Throwable $e) {
|
||||
// 表尚未创建(还没有蜘蛛来访过):返回空列表而非报错
|
||||
$this->result->setCount(0)->success([]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 汇总统计:各蜘蛛 今日/7日/30日/总量 + 近30日逐日趋势(图表用)
|
||||
*/
|
||||
public function stats()
|
||||
{
|
||||
$labels = SpiderDetect::labels();
|
||||
$today = date('Y-m-d');
|
||||
$d7 = date('Y-m-d', strtotime('-6 days'));
|
||||
$d30 = date('Y-m-d', strtotime('-29 days'));
|
||||
|
||||
$summary = [];
|
||||
$trend = ['dates' => [], 'series' => []];
|
||||
|
||||
try {
|
||||
$rows = Db::name('spider_stat')
|
||||
->where('stat_date', '>=', $d30)
|
||||
->select()
|
||||
->toArray();
|
||||
$totalRows = Db::name('spider_stat')
|
||||
->field('spider, SUM(`count`) AS total')
|
||||
->group('spider')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 各蜘蛛汇总
|
||||
$map = [];
|
||||
foreach ($totalRows as $r) {
|
||||
$map[$r['spider']] = [
|
||||
'spider' => $r['spider'],
|
||||
'label' => $labels[$r['spider']] ?? $r['spider'],
|
||||
'today' => 0,
|
||||
'week' => 0,
|
||||
'month' => 0,
|
||||
'total' => (int) $r['total'],
|
||||
];
|
||||
}
|
||||
foreach ($rows as $r) {
|
||||
$key = $r['spider'];
|
||||
if (! isset($map[$key])) {
|
||||
continue;
|
||||
}
|
||||
$c = (int) $r['count'];
|
||||
$map[$key]['month'] += $c;
|
||||
if ($r['stat_date'] >= $d7) {
|
||||
$map[$key]['week'] += $c;
|
||||
}
|
||||
if ($r['stat_date'] === $today) {
|
||||
$map[$key]['today'] += $c;
|
||||
}
|
||||
}
|
||||
usort($map, fn ($a, $b) => $b['total'] <=> $a['total']);
|
||||
$summary = array_values($map);
|
||||
|
||||
// 近30日逐日趋势(每蜘蛛一条线)
|
||||
$dates = [];
|
||||
for ($i = 29; $i >= 0; $i--) {
|
||||
$dates[] = date('Y-m-d', strtotime("-{$i} days"));
|
||||
}
|
||||
$trend['dates'] = $dates;
|
||||
$bySpider = [];
|
||||
foreach ($rows as $r) {
|
||||
$bySpider[$r['spider']][$r['stat_date']] = (int) $r['count'];
|
||||
}
|
||||
foreach ($summary as $s) {
|
||||
$key = $s['spider'];
|
||||
$line = [];
|
||||
foreach ($dates as $d) {
|
||||
$line[] = $bySpider[$key][$d] ?? 0;
|
||||
}
|
||||
$trend['series'][] = ['name' => $s['label'], 'data' => $line];
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// 表未创建:返回空数据
|
||||
}
|
||||
|
||||
$this->result->success(['summary' => $summary, 'trend' => $trend]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理明细日志(保留最近 N 天,聚合表不动,历史报表不受影响)
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
if (! ($this->request->isAjax() && $this->request->isPost())) {
|
||||
$this->result->error('请求方式错误', 405);
|
||||
}
|
||||
$days = $this->request->param('days/d', 30);
|
||||
$days = max(1, min(365, $days));
|
||||
try {
|
||||
$count = Db::name('spider_log')
|
||||
->where('create_at', '<', time() - $days * 86400)
|
||||
->delete();
|
||||
$this->result->success('', "已清理 {$count} 条 {$days} 天前的明细日志");
|
||||
} catch (\Throwable $e) {
|
||||
$this->result->error('清理失败: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user