- 新增访问统计:visitstats 服务与查询、visit_capture 中间件、爬虫/来源识别、管理端 analytics 页面 - 新增侧边栏:sidebar 服务与 handler、管理端 sidebar 配置页、前端侧边栏组件 - 新增 widget 嵌入代码生成(widgetCode)与 widgetApi - 遥测逻辑迁移至 handler 层,删除 service/telemetry - env 示例补充 Docker 部署可信代理 IP 说明
75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
"use client";
|
||
|
||
import Link from "next/link";
|
||
import { usePathname, useRouter } from "next/navigation";
|
||
import { useRef, type KeyboardEvent, type ReactNode } from "react";
|
||
import { BarChart3 } from "lucide-react";
|
||
import { AdminPageHeader } from "@/components/admin";
|
||
|
||
export const ANALYTICS_TABS: { href: string; label: string }[] = [
|
||
{ href: "/admin/analytics", label: "概览" },
|
||
{ href: "/admin/analytics/realtime", label: "实时" },
|
||
{ href: "/admin/analytics/sources", label: "来源分析" },
|
||
{ href: "/admin/analytics/pages", label: "受访页面" },
|
||
{ href: "/admin/analytics/visitors", label: "访客画像" },
|
||
{ href: "/admin/analytics/security", label: "爬虫与安全" },
|
||
{ href: "/admin/analytics/details", label: "访问明细" },
|
||
{ href: "/admin/analytics/settings", label: "设置" },
|
||
];
|
||
|
||
export default function AnalyticsShell({ children }: { children: ReactNode }) {
|
||
const pathname = usePathname();
|
||
const router = useRouter();
|
||
const navRefs = useRef<(HTMLAnchorElement | null)[]>([]);
|
||
|
||
// ←→/Home/End 键盘导航,范式同 SettingsShell(纵向改横向)
|
||
const onNavKeyDown = (e: KeyboardEvent<HTMLAnchorElement>, i: number) => {
|
||
if (
|
||
e.key !== "ArrowRight" &&
|
||
e.key !== "ArrowLeft" &&
|
||
e.key !== "Home" &&
|
||
e.key !== "End"
|
||
) {
|
||
return;
|
||
}
|
||
e.preventDefault();
|
||
let next = i;
|
||
if (e.key === "ArrowRight") next = (i + 1) % ANALYTICS_TABS.length;
|
||
else if (e.key === "ArrowLeft") next = (i + ANALYTICS_TABS.length - 1) % ANALYTICS_TABS.length;
|
||
else if (e.key === "Home") next = 0;
|
||
else next = ANALYTICS_TABS.length - 1;
|
||
navRefs.current[next]?.focus();
|
||
router.push(ANALYTICS_TABS[next].href);
|
||
};
|
||
|
||
return (
|
||
<div className="admin-analytics-page">
|
||
<AdminPageHeader
|
||
icon={BarChart3}
|
||
title="访问统计"
|
||
description="站点流量、来源、访客与安全事件的采集与分析"
|
||
/>
|
||
<nav className="admin-analytics-tabs" aria-label="访问统计分类">
|
||
{ANALYTICS_TABS.map((item, i) => {
|
||
const active = pathname === item.href;
|
||
return (
|
||
<Link
|
||
key={item.href}
|
||
ref={(el) => {
|
||
navRefs.current[i] = el;
|
||
}}
|
||
href={item.href}
|
||
className="admin-analytics-tab"
|
||
aria-current={active ? "page" : undefined}
|
||
onKeyDown={(e) => onNavKeyDown(e, i)}
|
||
>
|
||
{item.label}
|
||
</Link>
|
||
);
|
||
})}
|
||
</nav>
|
||
{children}
|
||
</div>
|
||
);
|
||
}
|