<?php

require_once __DIR__ . '/common.php';

admin_require_login();

$pdo       = db();
$adminUser = admin_current_user();
$siteTitle = get_setting('site.title', '六柱个人博客');

$errors = [];
$infos  = [];


$days = (int)($_GET['days'] ?? 1);
if (!in_array($days, [1, 7], true)) {
    $days = 1;
}

$now        = time();
$todayDate  = date('Y-m-d', $now);
$yesterday  = date('Y-m-d', $now - 86400);
$sinceTs    = $now - $days * 86400;
$sinceLabel = ($days === 1) ? '最近 1 天' : '最近 7 天';


$todayStats     = ['pv' => 0, 'uv' => 0, 'ip' => 0];
$yesterdayStats = ['pv' => 0, 'uv' => 0, 'ip' => 0];


$dailySeries = []; 

try {
    
    $stmt = $pdo->prepare("SELECT date, pv, uv, ip_count FROM visit_daily WHERE date IN (:d1, :d2)");
    $stmt->execute([':d1' => $todayDate, ':d2' => $yesterday]);
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        if ($row['date'] === $todayDate) {
            $todayStats = [
                'pv' => (int)$row['pv'],
                'uv' => (int)$row['uv'],
                'ip' => (int)$row['ip_count'],
            ];
        } elseif ($row['date'] === $yesterday) {
            $yesterdayStats = [
                'pv' => (int)$row['pv'],
                'uv' => (int)$row['uv'],
                'ip' => (int)$row['ip_count'],
            ];
        }
    }

    
    $sevenAgo = date('Y-m-d', $now - 6 * 86400);
    $stmt     = $pdo->prepare("
        SELECT date, pv, uv, ip_count
        FROM visit_daily
        WHERE date >= :start AND date <= :end
        ORDER BY date ASC
    ");
    $stmt->execute([':start' => $sevenAgo, ':end' => $todayDate]);
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $d = (string)$row['date'];
        $dailySeries[$d] = [
            'pv' => (int)$row['pv'],
            'uv' => (int)$row['uv'],
            'ip' => (int)$row['ip_count'],
        ];
    }
} catch (Throwable $e) {
    $errors[] = '无法读取访问汇总表 visit_daily（可能尚未初始化数据库）。';
}


$topLimit   = 200;
$visitRanks = []; 

try {
    $stmt = $pdo->prepare("
        SELECT
            url,
            COALESCE(article_id, 0) AS article_id,
            COUNT(*)                                 AS pv,
            COUNT(DISTINCT visitor_id)               AS uv,
            COUNT(DISTINCT ip)                       AS ip_cnt
        FROM visit_log
        WHERE visit_time >= :since
        GROUP BY url, COALESCE(article_id, 0)
        ORDER BY pv DESC
        LIMIT :limit
    ");
    $stmt->bindValue(':since', $sinceTs, PDO::PARAM_INT);
    $stmt->bindValue(':limit', $topLimit, PDO::PARAM_INT);
    $stmt->execute();
    $visitRanks = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $e) {
    $errors[] = '无法读取访问排行（visit_log）数据。';
}


$suspiciousIps = [];
try {
    $suspSince = $now - 7 * 86400;
    $threshold = 50;
    $stmt      = $pdo->prepare("
        SELECT
            ip,
            COUNT(*)                         AS pv,
            COUNT(DISTINCT visitor_id)       AS uv,
            MIN(visit_time)                  AS first_visit,
            MAX(visit_time)                  AS last_visit
        FROM visit_log
        WHERE visit_time >= :since
          AND ip IS NOT NULL
          AND ip <> ''
        GROUP BY ip
        HAVING pv >= :threshold
        ORDER BY pv DESC
    ");
    $stmt->execute([
        ':since'     => $suspSince,
        ':threshold' => $threshold,
    ]);
    $suspiciousIps = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $e) {
    
}


$logsDays = (int)($_GET['logs_days'] ?? 1);
if (!in_array($logsDays, [1, 7], true)) {
    $logsDays = 1;
}
$logsIp    = trim((string)($_GET['logs_ip'] ?? ''));
$logsUrl   = trim((string)($_GET['logs_url'] ?? ''));
$logsRef   = trim((string)($_GET['logs_ref'] ?? ''));
$logsSince = $now - $logsDays * 86400;
$logsLimit = 200;
$recentLogs = [];

try {
    $where  = ['visit_time >= :since'];
    $params = [':since' => $logsSince];

    if ($logsIp !== '') {
        $where[]       = 'ip = :ip';
        $params[':ip'] = $logsIp;
    }
    if ($logsUrl !== '') {
        $where[]           = 'url LIKE :url_kw';
        $params[':url_kw'] = '%' . $logsUrl . '%';
    }
    if ($logsRef !== '') {
        $where[]           = 'referrer LIKE :ref_kw';
        $params[':ref_kw'] = '%' . $logsRef . '%';
    }

    $sql = "
        SELECT visit_time, url, ip, visitor_id, is_mobile, referrer
        FROM visit_log
        WHERE " . implode(' AND ', $where) . "
        ORDER BY visit_time DESC
        LIMIT :limit
    ";
    $stmt = $pdo->prepare($sql);
    foreach ($params as $key => $val) {
        if ($key === ':since') {
            $stmt->bindValue($key, (int)$val, PDO::PARAM_INT);
        } else {
            $stmt->bindValue($key, $val);
        }
    }
    $stmt->bindValue(':limit', $logsLimit, PDO::PARAM_INT);
    $stmt->execute();
    $recentLogs = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $e) {
    
}


$articleRankTotal = [];
$articleRank7d    = [];
try {
    $stmt = $pdo->query("
        SELECT id, title, view_count, comment_count, like_count
        FROM articles
        WHERE status = 'published'
        ORDER BY view_count DESC, id DESC
        LIMIT 20
    ");
    $articleRankTotal = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $e) {
    $articleRankTotal = [];
}

try {
    $sinceArticle = $now - 6 * 86400;
    $stmt = $pdo->prepare("
        SELECT
            v.article_id,
            a.title,
            COUNT(*)                     AS pv,
            COUNT(DISTINCT v.visitor_id) AS uv,
            MAX(v.visit_time)            AS last_visit
        FROM visit_log v
        JOIN articles a ON a.id = v.article_id
        WHERE v.article_id IS NOT NULL
          AND v.visit_time >= :since
          AND a.status = 'published'
        GROUP BY v.article_id
        ORDER BY pv DESC
        LIMIT 20
    ");
    $stmt->execute([':since' => $sinceArticle]);
    $articleRank7d = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $e) {
    $articleRank7d = [];
}


$sourceOverview = [
    'direct_pv'   => 0,
    'internal_pv' => 0,
    'external_pv' => 0,
];
$sourceDomains = [];   
$searchEngines = [];   

try {
    $refSince = $now - 6 * 86400;
    $stmt = $pdo->prepare("
        SELECT referrer, COUNT(*) AS pv
        FROM visit_log
        WHERE visit_time >= :since
        GROUP BY referrer
    ");
    $stmt->execute([':since' => $refSince]);

    $selfHost = '';
    if (!empty($_SERVER['HTTP_HOST']) && is_string($_SERVER['HTTP_HOST'])) {
        $selfHost = strtolower((string)preg_replace('/:\\d+$/', '', $_SERVER['HTTP_HOST']));
    }

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $pv  = (int)($row['pv'] ?? 0);
        $ref = $row['referrer'] ?? null;

        if ($pv <= 0) {
            continue;
        }

        if ($ref === null || $ref === '') {
            $sourceOverview['direct_pv'] += $pv;
            continue;
        }

        $refStr = (string)$ref;
        $host   = '';
        $parsed = @parse_url($refStr);
        if (is_array($parsed) && !empty($parsed['host'])) {
            $host = strtolower($parsed['host']);
        } elseif (isset($refStr[0]) && $refStr[0] === '/') {
            
            $host = $selfHost;
        }

        if ($host === '') {
            
            $sourceOverview['direct_pv'] += $pv;
            continue;
        }

        
        if ($selfHost !== '' && $host === $selfHost) {
            $sourceOverview['internal_pv'] += $pv;
            continue;
        }

        
        $sourceOverview['external_pv'] += $pv;
        if (!isset($sourceDomains[$host])) {
            $sourceDomains[$host] = 0;
        }
        $sourceDomains[$host] += $pv;

        
        $engine = null;
        if (strpos($host, 'baidu.') !== false) {
            $engine = '百度';
        } elseif (strpos($host, 'google.') !== false) {
            $engine = 'Google';
        } elseif (strpos($host, 'bing.') !== false) {
            $engine = 'Bing';
        } elseif (strpos($host, 'so.com') !== false || strpos($host, '360.cn') !== false) {
            $engine = '360 搜索';
        } elseif (strpos($host, 'sogou.com') !== false) {
            $engine = '搜狗';
        } elseif (strpos($host, 'sm.cn') !== false) {
            $engine = '神马';
        } elseif (strpos($host, 'yahoo.') !== false) {
            $engine = 'Yahoo';
        }

        if ($engine !== null) {
            if (!isset($searchEngines[$engine])) {
                $searchEngines[$engine] = 0;
            }
            $searchEngines[$engine] += $pv;
        }
    }

    if ($sourceDomains) {
        arsort($sourceDomains);
        
        $sourceDomains = array_slice($sourceDomains, 0, 30, true);
    }
    if ($searchEngines) {
        arsort($searchEngines);
    }
} catch (Throwable $e) {
    $sourceOverview = [
        'direct_pv'   => 0,
        'internal_pv' => 0,
        'external_pv' => 0,
    ];
    $sourceDomains = [];
    $searchEngines = [];
}


$categoryFlow7d = [];
$tagFlow7d      = [];

try {
    $sinceCat = $now - 6 * 86400;
    $stmt = $pdo->prepare("
        SELECT
            c.id   AS category_id,
            c.name AS category_name,
            COUNT(*)                     AS pv,
            COUNT(DISTINCT v.visitor_id) AS uv
        FROM visit_log v
        JOIN articles a   ON a.id = v.article_id
        JOIN categories c ON c.id = a.category_id
        WHERE v.article_id IS NOT NULL
          AND v.visit_time >= :since
          AND a.status = 'published'
        GROUP BY c.id
        ORDER BY pv DESC
        LIMIT 20
    ");
    $stmt->execute([':since' => $sinceCat]);
    $categoryFlow7d = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $e) {
    $categoryFlow7d = [];
}

try {
    $sinceTag = $now - 6 * 86400;
    $stmt = $pdo->prepare("
        SELECT
            t.id    AS tag_id,
            t.name  AS tag_name,
            COUNT(*)                     AS pv,
            COUNT(DISTINCT v.visitor_id) AS uv
        FROM visit_log v
        JOIN articles a      ON a.id = v.article_id
        JOIN article_tag at2 ON at2.article_id = a.id
        JOIN tags t          ON t.id = at2.tag_id
        WHERE v.article_id IS NOT NULL
          AND v.visit_time >= :since
          AND a.status = 'published'
        GROUP BY t.id
        ORDER BY pv DESC
        LIMIT 20
    ");
    $stmt->execute([':since' => $sinceTag]);
    $tagFlow7d = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $e) {
    $tagFlow7d = [];
}


$newReturningStats = [
    'uv_total'  => 0,
    'uv_new'    => 0,
    'uv_return' => 0,
];

try {
    $visitorSince = $now - 6 * 86400;
    $stmt = $pdo->prepare("
        SELECT visitor_id, COUNT(*) AS cnt
        FROM visit_log
        WHERE visit_time >= :since
          AND visitor_id IS NOT NULL
          AND visitor_id <> ''
        GROUP BY visitor_id
    ");
    $stmt->execute([':since' => $visitorSince]);
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $cnt = (int)($row['cnt'] ?? 0);
        if ($cnt <= 0) {
            continue;
        }
        $newReturningStats['uv_total']++;
        if ($cnt === 1) {
            $newReturningStats['uv_new']++;
        } else {
            $newReturningStats['uv_return']++;
        }
    }
} catch (Throwable $e) {
    $newReturningStats = [
        'uv_total'  => 0,
        'uv_new'    => 0,
        'uv_return' => 0,
    ];
}


$searchHotTerms = []; 
try {
    $searchSince = $now - 6 * 86400;
    $stmt = $pdo->prepare("
        SELECT url, visitor_id
        FROM visit_log
        WHERE visit_time >= :since
          AND url LIKE '%search.php%'
    ");
    $stmt->execute([':since' => $searchSince]);

    $termPv       = [];
    $termVisitors = [];

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $url       = (string)($row['url'] ?? '');
        $visitorId = (string)($row['visitor_id'] ?? '');
        if ($url === '') {
            continue;
        }
        $parsed = @parse_url($url);
        if (!is_array($parsed) || empty($parsed['query'])) {
            continue;
        }
        parse_str($parsed['query'], $query);
        if (empty($query['q'])) {
            continue;
        }
        $term = trim((string)$query['q']);
        if ($term === '') {
            continue;
        }

        if (!isset($termPv[$term])) {
            $termPv[$term]       = 0;
            $termVisitors[$term] = [];
        }
        $termPv[$term]++;
        if ($visitorId !== '') {
            $termVisitors[$term][$visitorId] = true;
        }
    }

    foreach ($termPv as $term => $pv) {
        $uv = isset($termVisitors[$term]) ? count($termVisitors[$term]) : 0;
        $searchHotTerms[] = [
            'term' => $term,
            'pv'   => (int)$pv,
            'uv'   => (int)$uv,
        ];
    }

    if ($searchHotTerms) {
        usort($searchHotTerms, function (array $a, array $b): int {
            return $b['pv'] <=> $a['pv'];
        });
        if (count($searchHotTerms) > 20) {
            $searchHotTerms = array_slice($searchHotTerms, 0, 20);
        }
    }
} catch (Throwable $e) {
    $searchHotTerms = [];
}

?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>流量统计 - <?php echo h($siteTitle); ?></title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        html, body { height:100%;  margin:0; padding:0; }
        body {
            margin: 0; padding:0;
            font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;
            background: #0f172a;
            color: #e5e7eb;
        }
        a { color:#60a5fa; text-decoration:none; }
        a:hover { text-decoration:underline; }

        .topbar {
            background:#020617;
            border-bottom:1px solid #1f2937;
            padding:18px 16px 6px;
            display:flex;
            align-items:flex-start;
            justify-content:space-between;
         margin:0;  margin-top:-12px; }
        .topbar-title {
            font-size:16px;
            font-weight:600;
        }
        .topbar-user {
            font-size:13px;
            color:#9ca3af;
        }
        .topbar-nav a {
            margin-left:10px;
            font-size:13px;
        }

        .layout {
            max-width:1200px;
            margin:0 auto;
            padding:16px;
        }
        .cards {
            display:grid;
            grid-template-columns:minmax(0,1.2fr) minmax(0,2fr);
            gap:16px;
        }
        .cards-2col {
            display:grid;
            grid-template-columns:repeat(2,minmax(0,1fr));
            gap:16px;
            margin-top:16px;
        }
        .card {
            background:#020617;
            border-radius:6px;
            border:1px solid #1f2937;
            padding:10px 12px;
        }
        .card-title {
            font-size:14px;
            font-weight:600;
            margin-bottom:4px;
        }
        .card-sub {
            font-size:12px;
            color:#9ca3af;
            margin-bottom:6px;
        }

        .stat-grid {
            display:flex;
            gap:12px;
            flex-wrap:wrap;
        }
        .stat-block {
            padding:6px 8px;
            border-radius:6px;
            background:#020617;
            border:1px solid #1f2937;
            min-width:140px;
        }
        .stat-number {
            font-size:18px;
            font-weight:700;
        }
        .stat-label {
            font-size:11px;
            color:#9ca3af;
            margin-left:4px;
        }
        .stat-sub {
            font-size:11px;
            color:#9ca3af;
            margin-top:2px;
        }

        table {
            width:100%;
            border-collapse:collapse;
            font-size:12px;
        }
        th, td {
            padding:4px 6px;
            border-bottom:1px solid #1f2937;
            text-align:left;
        }
        th {
            background:#020617;
            font-weight:600;
            font-size:12px;
        }
        tr:nth-child(even) td {
            background:#020617;
        }

        .trend-table td { white-space:nowrap; }

        .msg-error {
            background:#3f2a2a;
            border:1px solid #fecaca;
            color:#fee2e2;
            padding:6px 8px;
            border-radius:4px;
            font-size:12px;
            margin:8px 0;
        }
        .msg-info {
            background:#1d3a5f;
            border:1px solid #bfdbfe;
            color:#dbeafe;
            padding:6px 8px;
            border-radius:4px;
            font-size:12px;
            margin:8px 0;
        }

        .footer {
            margin-top:16px;
            font-size:11px;
            color:#6b7280;
            text-align:center;
        }
    </style>
</head>
<body style="margin:0;padding:0;"><div class="topbar">
        <div class="topbar-title">流量统计</div>
        <div class="topbar-user">
            管理员：<?php echo h($adminUser['nickname'] ?? $adminUser['email'] ?? ''); ?>
            <span class="topbar-nav">
                <a href="index.php">仪表板</a>
                <a href="articles.php">文章</a>
                <a href="categories.php">分类</a>
                <a href="tags.php">&#26631;&#31614;</a>
                <a href="comments.php">评论</a>
                <a href="links.php">友链</a>
                <a href="media.php">文件</a>
                <a href="users.php">会员</a>
                <a href="sensitive_words.php">敏感词</a>
                <a href="stats.php">流量</a>
                <a href="security.php">防护</a>
                <a href="logs.php">日志</a>
                <a href="settings.php">设置</a>
                <a href="backup_sqlite.php">&#25968;&#25454;</a>
                <a href="../index.php">前台</a>
                <a href="../logout.php">退出</a>
            </span>
        </div>
    </div>

    <div class="layout">
        <?php if ($errors): ?>
            <div class="msg-error">
                <?php foreach ($errors as $e): ?>
                    <div><?php echo h($e); ?></div>
                <?php endforeach; ?>
            </div>
        <?php endif; ?>
        <?php if ($infos): ?>
            <div class="msg-info">
                <?php foreach ($infos as $m): ?>
                    <div><?php echo h($m); ?></div>
                <?php endforeach; ?>
            </div>
        <?php endif; ?>

        <div class="cards">
            
            <div class="card">
                <div class="card-title">访问概览</div>
                <div class="card-sub">基于 visit_daily 汇总数据。</div>
                <div class="stat-grid">
                    <div class="stat-block">
                        <div>
                            <span class="stat-number"><?php echo $todayStats['pv']; ?></span>
                            <span class="stat-label">今日 PV</span>
                        </div>
                        <div class="stat-sub">
                            UV：<?php echo $todayStats['uv']; ?> / IP：<?php echo $todayStats['ip']; ?>
                        </div>
                    </div>
                    <div class="stat-block">
                        <div>
                            <span class="stat-number"><?php echo $yesterdayStats['pv']; ?></span>
                            <span class="stat-label">昨日 PV</span>
                        </div>
                        <div class="stat-sub">
                            UV：<?php echo $yesterdayStats['uv']; ?> / IP：<?php echo $yesterdayStats['ip']; ?>
                        </div>
                    </div>
                </div>

                <div style="margin-top:10px;">
                    <div class="card-sub">最近 7 天趋势（按日）</div>
                    <table class="trend-table">
                        <thead>
                        <tr>
                            <th>日期</th>
                            <th>PV</th>
                            <th>UV</th>
                            <th>IP</th>
                        </tr>
                        </thead>
                        <tbody>
                        <?php if ($dailySeries): ?>
                            <?php foreach ($dailySeries as $d => $row): ?>
                                <tr>
                                    <td><?php echo h($d); ?></td>
                                    <td><?php echo (int)$row['pv']; ?></td>
                                    <td><?php echo (int)$row['uv']; ?></td>
                                    <td><?php echo (int)$row['ip']; ?></td>
                                </tr>
                            <?php endforeach; ?>
                        <?php else: ?>
                            <tr><td colspan="4">暂无按日统计数据。</td></tr>
                        <?php endif; ?>
                        </tbody>
                    </table>
                </div>
            </div>

            
            <div class="card">
                <div class="card-title">访问排行（URL）</div>
                <div class="card-sub"><?php echo h($sinceLabel); ?>，按 PV 排序，最多 <?php echo $topLimit; ?> 条。</div>
                <div style="margin-bottom:6px;">
                    <form method="get" style="font-size:12px;">
                        统计范围：
                        <select name="days">
                            <option value="1" <?php if ($days === 1) echo 'selected'; ?>>最近 1 天</option>
                            <option value="7" <?php if ($days === 7) echo 'selected'; ?>>最近 7 天</option>
                        </select>
                        <button type="submit">切换</button>
                    </form>
                </div>
                <table>
                    <thead>
                    <tr>
                        <th>URL / 页面</th>
                        <th>PV</th>
                        <th>UV</th>
                        <th>IP</th>
                    </tr>
                    </thead>
                    <tbody>
                    <?php if ($visitRanks): ?>
                        <?php foreach ($visitRanks as $row): ?>
                            <tr>
                                <td><?php echo h((string)($row['url'] ?? '')); ?></td>
                                <td><?php echo (int)$row['pv']; ?></td>
                                <td><?php echo (int)$row['uv']; ?></td>
                                <td><?php echo (int)$row['ip_cnt']; ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                        <tr><td colspan="4">在所选时间范围内没有访问记录。</td></tr>
                    <?php endif; ?>
                    </tbody>
                </table>
            </div>
        </div>

        
        <div class="cards-2col">
            <div class="card">
                <div class="card-title">文章访问排行（按总浏览量，Top 20）</div>
                <div class="card-sub">基于 articles.view_count 字段。</div>
                <table>
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>标题</th>
                        <th>总浏览</th>
                        <th>评论</th>
                        <th>点赞</th>
                    </tr>
                    </thead>
                    <tbody>
                    <?php if ($articleRankTotal): ?>
                        <?php foreach ($articleRankTotal as $a): ?>
                            <tr>
                                <td><?php echo (int)$a['id']; ?></td>
                                <td>
                                    <a href="../post.php?id=<?php echo (int)$a['id']; ?>" target="_blank">
                                        <?php echo h(mb_substr($a['title'] ?? '', 0, 30, 'UTF-8')); ?>
                                    </a>
                                </td>
                                <td><?php echo (int)($a['view_count'] ?? 0); ?></td>
                                <td><?php echo (int)($a['comment_count'] ?? 0); ?></td>
                                <td><?php echo (int)($a['like_count'] ?? 0); ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                        <tr><td colspan="5">暂时还没有文章浏览统计。</td></tr>
                    <?php endif; ?>
                    </tbody>
                </table>
            </div>

            <div class="card">
                <div class="card-title">最近 7 天文章访问排行（按 PV，Top 20）</div>
                <div class="card-sub">数据来自 visit_log 表，仅统计已发布文章。</div>
                <table>
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>标题</th>
                        <th>7 日 PV</th>
                        <th>7 日 UV</th>
                        <th>最近访问</th>
                    </tr>
                    </thead>
                    <tbody>
                    <?php if ($articleRank7d): ?>
                        <?php foreach ($articleRank7d as $a): ?>
                            <tr>
                                <td><?php echo (int)$a['article_id']; ?></td>
                                <td>
                                    <a href="../post.php?id=<?php echo (int)$a['article_id']; ?>" target="_blank">
                                        <?php echo h(mb_substr($a['title'] ?? '', 0, 30, 'UTF-8')); ?>
                                    </a>
                                </td>
                                <td><?php echo (int)$a['pv']; ?></td>
                                <td><?php echo (int)$a['uv']; ?></td>
                                <td><?php echo date('m-d H:i', (int)$a['last_visit']); ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                        <tr><td colspan="5">最近 7 天暂时没有文章访问记录。</td></tr>
                    <?php endif; ?>
                    </tbody>
                </table>
            </div>
        </div>

        
        <div class="cards-2col">
            <div class="card">
                <div class="card-title">分类 / 标签流量（最近 7 天）</div>
                <div class="card-sub">按最近 7 天访问日志统计，每个分类 / 标签的 PV / UV。</div>
                <div class="card-sub" style="margin-bottom:4px;">按分类统计（Top 20）</div>
                <table>
                    <thead>
                    <tr>
                        <th>分类</th>
                        <th>7 日 PV</th>
                        <th>7 日 UV</th>
                    </tr>
                    </thead>
                    <tbody>
                    <?php if ($categoryFlow7d): ?>
                        <?php foreach ($categoryFlow7d as $c): ?>
                            <tr>
                                <td><?php echo h($c['category_name']); ?></td>
                                <td><?php echo (int)$c['pv']; ?></td>
                                <td><?php echo (int)$c['uv']; ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                        <tr><td colspan="3">最近 7 天暂时没有分类访问统计。</td></tr>
                    <?php endif; ?>
                    </tbody>
                </table>

                <div class="card-sub" style="margin-top:8px;">按标签统计（Top 20）</div>
                <table>
                    <thead>
                    <tr>
                        <th>标签</th>
                        <th>7 日 PV</th>
                        <th>7 日 UV</th>
                    </tr>
                    </thead>
                    <tbody>
                    <?php if ($tagFlow7d): ?>
                        <?php foreach ($tagFlow7d as $t): ?>
                            <tr>
                                <td><?php echo h($t['tag_name']); ?></td>
                                <td><?php echo (int)$t['pv']; ?></td>
                                <td><?php echo (int)$t['uv']; ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                        <tr><td colspan="3">最近 7 天标签还没有产生访问统计。</td></tr>
                    <?php endif; ?>
                    </tbody>
                </table>
            </div>

            <div class="card">
                <div class="card-title">新访客 vs 回访访客（最近 7 天）</div>
                <div class="card-sub">基于 visitor_id，统计最近 7 天仅访问 1 次（新）与访问多次（回访）的访客数量。</div>
                <?php
                $uvTotal  = (int)$newReturningStats['uv_total'];
                $uvNew    = (int)$newReturningStats['uv_new'];
                $uvReturn = (int)$newReturningStats['uv_return'];
                $pctNew   = $uvTotal > 0 ? round($uvNew * 100 / $uvTotal, 1) : 0;
                $pctRet   = $uvTotal > 0 ? round($uvReturn * 100 / $uvTotal, 1) : 0;
                ?>
                <table>
                    <thead>
                    <tr>
                        <th>类型</th>
                        <th>人数（UV）</th>
                        <th>占比</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                        <td>新访客（7 天内仅访问 1 次）</td>
                        <td><?php echo $uvNew; ?></td>
                        <td><?php echo $pctNew; ?>%</td>
                    </tr>
                    <tr>
                        <td>回访访客（7 天内访问 ≥ 2 次）</td>
                        <td><?php echo $uvReturn; ?></td>
                        <td><?php echo $pctRet; ?>%</td>
                    </tr>
                    <tr>
                        <td>合计</td>
                        <td><?php echo $uvTotal; ?></td>
                        <td>100%</td>
                    </tr>
                    </tbody>
                </table>

                <div class="card-sub" style="margin-top:8px;">站内搜索热词（最近 7 天，Top 20）</div>
                <table>
                    <thead>
                    <tr>
                        <th>关键词</th>
                        <th>PV</th>
                        <th>UV</th>
                    </tr>
                    </thead>
                    <tbody>
                    <?php if ($searchHotTerms): ?>
                        <?php foreach ($searchHotTerms as $termRow): ?>
                            <tr>
                                <td><?php echo h($termRow['term']); ?></td>
                                <td><?php echo (int)$termRow['pv']; ?></td>
                                <td><?php echo (int)$termRow['uv']; ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                        <tr><td colspan="3">最近 7 天内暂未产生站内搜索记录，或搜索功能访问较少。</td></tr>
                    <?php endif; ?>
                    </tbody>
                </table>
            </div>
        </div>

        <div class="cards-2col">
            <div class="card">
                <div class="card-title">来源概览（最近 7 天）</div>
                <div class="card-sub">按 Referrer 粗略统计直接访问 / 站内跳转 / 外部来源。</div>
                <table>
                    <thead>
                    <tr>
                        <th>类型</th>
                        <th>PV</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                        <td>直接访问（无 Referrer）</td>
                        <td><?php echo (int)$sourceOverview['direct_pv']; ?></td>
                    </tr>
                    <tr>
                        <td>站内跳转</td>
                        <td><?php echo (int)$sourceOverview['internal_pv']; ?></td>
                    </tr>
                    <tr>
                        <td>外部来源</td>
                        <td><?php echo (int)$sourceOverview['external_pv']; ?></td>
                    </tr>
                    </tbody>
                </table>

                <div class="card-sub" style="margin-top:8px;">外部域名排行（Top 30）</div>
                <table>
                    <thead>
                    <tr>
                        <th>域名</th>
                        <th>PV</th>
                    </tr>
                    </thead>
                    <tbody>
                    <?php if ($sourceDomains): ?>
                        <?php foreach ($sourceDomains as $host => $pv): ?>
                            <tr>
                                <td><?php echo h($host); ?></td>
                                <td><?php echo (int)$pv; ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                        <tr><td colspan="2">最近 7 天内暂无外部来源统计。</td></tr>
                    <?php endif; ?>
                    </tbody>
                </table>
            </div>

            <div class="card">
                <div class="card-title">搜索引擎来源（最近 7 天）</div>
                <div class="card-sub">按常见搜索引擎域名粗略归类，仅按 PV 统计。</div>
                <table>
                    <thead>
                    <tr>
                        <th>搜索引擎</th>
                        <th>PV</th>
                    </tr>
                    </thead>
                    <tbody>
                    <?php if ($searchEngines): ?>
                        <?php foreach ($searchEngines as $engine => $pv): ?>
                            <tr>
                                <td><?php echo h($engine); ?></td>
                                <td><?php echo (int)$pv; ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php else: ?>
                        <tr><td colspan="2">最近 7 天内暂无明显的搜索引擎来源。</td></tr>
                    <?php endif; ?>
                    </tbody>
                </table>
            </div>
        </div>

        
        <div class="card" style="margin-top:16px;">
            <div class="card-title">最近 7 天高频 IP（PV ≥ 50）</div>
            <div class="card-sub">仅展示统计结果，如需拉黑请前往“防护”模块操作。</div>
            <table>
                <thead>
                <tr>
                    <th>IP</th>
                    <th>PV</th>
                    <th>UV</th>
                    <th>首次访问</th>
                    <th>最后访问</th>
                </tr>
                </thead>
                <tbody>
                <?php if ($suspiciousIps): ?>
                    <?php foreach ($suspiciousIps as $ipRow): ?>
                        <tr>
                            <td><?php echo h($ipRow['ip']); ?></td>
                            <td><?php echo (int)$ipRow['pv']; ?></td>
                            <td><?php echo (int)$ipRow['uv']; ?></td>
                            <td><?php echo date('m-d H:i', (int)$ipRow['first_visit']); ?></td>
                            <td><?php echo date('m-d H:i', (int)$ipRow['last_visit']); ?></td>
                        </tr>
                    <?php endforeach; ?>
                <?php else: ?>
                    <tr><td colspan="5">最近 7 天内暂未发现 PV ≥ 50 的高频 IP。</td></tr>
                <?php endif; ?>
                </tbody>
            </table>
        </div>

        
        <div class="card" style="margin-top:16px;">
            <div class="card-title">访问明细（最近 <?php echo (int)$logsDays; ?> 天，最多 200 条）</div>
            <div class="card-sub">可按 IP / URL 关键字 / Referrer 关键字筛选最近访问记录。</div>
            <form method="get" style="font-size:12px;margin-bottom:6px;display:flex;flex-wrap:wrap;gap:6px;align-items:center;">
                <span>时间范围：</span>
                <select name="logs_days">
                    <option value="1" <?php if ($logsDays === 1) echo 'selected'; ?>>最近 1 天</option>
                    <option value="7" <?php if ($logsDays === 7) echo 'selected'; ?>>最近 7 天</option>
                </select>
                <span>IP：</span>
                <input type="text" name="logs_ip" value="<?php echo h($logsIp); ?>" style="width:120px;">
                <span>URL 包含：</span>
                <input type="text" name="logs_url" value="<?php echo h($logsUrl); ?>" style="width:150px;">
                <span>Referrer 包含：</span>
                <input type="text" name="logs_ref" value="<?php echo h($logsRef); ?>" style="width:150px;">
                <button type="submit">筛选</button>
            </form>
            <table>
                <thead>
                <tr>
                    <th>时间</th>
                    <th>URL</th>
                    <th>IP</th>
                    <th>访客 ID</th>
                    <th>设备</th>
                    <th>Referrer</th>
                </tr>
                </thead>
                <tbody>
                <?php if ($recentLogs): ?>
                    <?php foreach ($recentLogs as $log): ?>
                        <tr>
                            <td><?php echo date('m-d H:i', (int)$log['visit_time']); ?></td>
                            <td><?php echo h((string)($log['url'] ?? '')); ?></td>
                            <td><?php echo h((string)($log['ip'] ?? '')); ?></td>
                            <td><?php echo h((string)($log['visitor_id'] ?? '')); ?></td>
                            <td><?php echo !empty($log['is_mobile']) ? '移动' : '桌面'; ?></td>
                            <td><?php echo h((string)($log['referrer'] ?? '')); ?></td>
                        </tr>
                    <?php endforeach; ?>
                <?php else: ?>
                    <tr><td colspan="6">在所选时间范围内没有符合条件的访问记录。</td></tr>
                <?php endif; ?>
                </tbody>
            </table>
        </div>

        <div class="footer">
            本页基于 visit_log / visit_daily 实时统计，访问明细仅保留最近 7 天，如需更细粒度分析，可配合“防护”模块查看。
        </div>
    </div>
</body>
</html>
