- 新增访问统计:visitstats 服务与查询、visit_capture 中间件、爬虫/来源识别、管理端 analytics 页面 - 新增侧边栏:sidebar 服务与 handler、管理端 sidebar 配置页、前端侧边栏组件 - 新增 widget 嵌入代码生成(widgetCode)与 widgetApi - 遥测逻辑迁移至 handler 层,删除 service/telemetry - env 示例补充 Docker 部署可信代理 IP 说明
41 lines
1.5 KiB
TypeScript
41 lines
1.5 KiB
TypeScript
import { Fragment } from "react";
|
||
import type { SidebarBlockRef, SidebarWidgetPublic } from "@/lib/sidebarMeta";
|
||
import { renderSidebarBlock, type SidebarBlockProps } from "./registry";
|
||
|
||
// 页面从本文件导入该类型(registry 中定义)
|
||
export type { SidebarBlockProps };
|
||
import CustomWidgetBlock from "./CustomWidgetBlock";
|
||
|
||
// 按管理端配置渲染一列侧栏块:
|
||
// - 内置块经注册表解析,未知 key / 数据缺失静默跳过;
|
||
// - 自定义工具引用已删除或停用(公开载荷不含)时静默跳过;
|
||
// - className 缺省时输出 Fragment,布局容器(gap/space-y、sticky、限高)由页面自行决定。
|
||
export default function SidebarRenderer({
|
||
blocks,
|
||
widgets,
|
||
props,
|
||
className,
|
||
}: {
|
||
blocks: SidebarBlockRef[];
|
||
widgets: SidebarWidgetPublic[];
|
||
props: SidebarBlockProps;
|
||
className?: string;
|
||
}) {
|
||
const items = blocks
|
||
.map((ref, i) => {
|
||
if (ref.widget) {
|
||
const widget = widgets.find((x) => x.id === ref.widget);
|
||
if (!widget) return null;
|
||
return <CustomWidgetBlock key={`w-${widget.id}-${i}`} widget={widget} viewer={props.user} />;
|
||
}
|
||
if (!ref.key) return null;
|
||
const node = renderSidebarBlock(ref.key, props);
|
||
if (node === null) return null;
|
||
return <Fragment key={`k-${ref.key}-${i}`}>{node}</Fragment>;
|
||
})
|
||
.filter((x) => x !== null);
|
||
|
||
if (items.length === 0) return null;
|
||
return className ? <div className={className}>{items}</div> : <>{items}</>;
|
||
}
|