# 控制台前端结构 本文件描述当前控制台前端的真实结构,目标是帮助后续页面开发、表格改造、布局治理和状态收口时快速找到正确入口。 相关规则建议一起参考: - 仓库根目录 `rules.md` - [前端布局指南](/home/ray/dev/linkong/planet/docs/technical/zh/frontend-layout-guidelines.md) ## 当前目标 控制台前端承担的是后台工作台,而不是展示型大屏。当前约束是: - 页面默认遵循单屏工作区 - 主交互在内部模块滚动,而不是依赖整页无限变长 - 列表、表格、分析页优先保证主工作区可见 - 通用布局、滚动条、表格滚动行为尽量复用,不要每页各写一套 ## 当前路由入口 主入口在: - [App.tsx](/home/ray/dev/linkong/planet/frontend/src/App.tsx) 当前正式后台路由已经由控制台接管: - `/admin` - `/users` - `/datasources` - `/data` - `/alerts/system` - `/alerts/bgp` - `/alerts/situational` - `/bgp` - `/ai` - `/earth-content` - `/collection-management` - `/settings` 这些路径渲染 [AdminRoutes.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/AdminRoutes.tsx),页面清单和菜单元信息来自 [manifest.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/routes/manifest.tsx)。控制台是唯一后台入口,不再维护并行控制台或回退路由。 `/earth` 是独立展示页,不属于控制台骨架。 ## 当前页面骨架 正式后台公共壳层在: - [AdminLayout.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/components/layout/AdminLayout.tsx) 职责: - 左侧导航、分组折叠和移动端抽屉 - 当前账号、版本、退出登录和主题切换 - 顶部搜索、面包屑和页面快捷入口 - 内容区单屏高度闭合 - 控制台内部滚动、表格、详情面板和移动端详情视图协调 后续正式控制台页面应适配 `AdminLayout` 和控制台页面模式;不要重新引入并行后台壳层。 ## 控制台分区加载策略 多 tab 页面由 [PlainResourcePages.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/PlainResourcePages.tsx) 统一承载当前的管理型和信息型工作台。分区加载规则是: - 初次进入页面只请求当前 active tab,不预先拉取所有 tab 的接口。 - 用户切换 tab 时懒加载该 tab;已经加载过的 tab 保留在本地 `states` 缓存中,切回时直接复用。 - 手动刷新、保存、测试、上传、生成教程等明确动作只刷新当前分区,避免把无关分区的接口一起打出去。 - 数据源目录的筛选条件变化会清掉内置源分区缓存,并按新筛选重新请求当前分区。 - 顶部 summary 只统计“已加载分区”,不把未访问 tab 误报成异常接口。 这样做是为了降低 Earth、AI、采集管理等多分区页面的冷启动压力,同时保留 tab 数量、状态和用户切换后的缓存体验。需要全量健康巡检时应走后端健康接口或显式刷新流程,不要依赖页面初始化时顺手拉所有业务接口。 ## 数据源采集队列 Admin 的数据源页把单源触发、表格勾选触发和触发全部统一接入浏览器下载列表式采集队列: - 队列状态由 [PlainResourcePages.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/PlainResourcePages.tsx) 管理,只保存当前会话中的可见任务,不用 `localStorage` 伪造历史。 - 任务进度优先消费 `/ws` 的 `datasource_tasks` channel;如果 WebSocket 未连接或没有及时返回,则轮询 `/api/v1/datasources/{id}/task-status`。 - 触发接口返回的 `triggered`、`skipped`、`failed` 会立即进入队列;刷新页面后只根据后端当前仍在 `running/pending/queued` 的数据源恢复队列。 - `内置源` 分区通过表格选择列收敛批量触发。没有勾选时主按钮是“触发全部”;勾选后同一个主按钮变成“触发已选 N”,不再提供手填 ID 的独立批量按钮。 - 页面内容流不再承载展开队列,避免全量触发后挤压列表和详情面板。右上角 actions 区的队列按钮沿用现有 `Button` 样式;空态使用 `ListChecks` 图标,有任务时只显示纯圆环总进度。点击后打开浮层,按运行中、失败、完成、跳过分组。 - 队列项可以跳转到对应数据源详情,失败项可以重试。详情页内的“采集任务”摘要只展示当前数据源最近任务,不承担保存配置职责。 - 运行中的单源采集按钮显示为“停止采集”;队列中未完成项右侧提供取消按钮。取消调用 `/api/v1/datasources/{source_id}/tasks/{task_id}/cancel`,后端语义是保留已提交批次并回滚未完成批次。 - 删除数据库数据和清理展示缓存也会进入同一队列,前端只展示任务状态,不假定接口同步完成。 这个队列是用户感知层,不替代后端调度状态。后端仍然是任务是否运行、完成、失败或跳过的唯一事实来源。 ## 控制台主题滑块 Admin 侧栏底部主题切换继续复用共享 [SegmentedControl.tsx](/home/ray/dev/linkong/planet/frontend/src/components/SegmentedControl/SegmentedControl.tsx),但主题变量在 [styles.css](/home/ray/dev/linkong/planet/frontend/src/admin/styles.css) 内跟随 `data-theme` 覆盖: - light 下使用 `--d-segment-bg: #eef3f9`、白色 slider 和轻投影。 - dark 下使用与 Docs 一致的深色底座、`#202938` slider 和深色外投影。 - 业务侧只隐藏文字 label 并保留 icon + tooltip,不重写 slider DOM。 ## 控制台状态颜色 Admin 的状态标签统一走 [StatusText](/home/ray/dev/linkong/planet/frontend/src/admin/patterns/patterns.tsx) 或 [Badge](/home/ray/dev/linkong/planet/frontend/src/admin/components/ui/badge.tsx),颜色变量来自 [styles.css](/home/ray/dev/linkong/planet/frontend/src/admin/styles.css)。新增状态时不要在页面里临时写 hex;先判断语义,再映射到现有 tone。 `StatusText` 是带圆点的指示灯:胶囊背景和边框保持组件原色,只让圆点和文字变成状态色。`Badge` 不带指示灯语义,可以使用同 tone 的浅色背景和边框强化信息层级。 | Tone | 颜色变量 | 语义 | 示例 | | --- | --- | --- | --- | | `success` | `--an-success` | 可用、成功、已连接、已启用 | 日志源 `可用`、采集 `成功` | | `warning` | `--an-warning` | 需要关注但不一定失败 | 日志文件 `暂无日志`、降级或跳过 | | `danger` | `--an-danger` | 失败、不可用、权限/连接错误 | `Docker 不可用`、接口失败 | | `info` / `running` | `--an-info` | 进行中、同步中、普通信息态 | `跟随中`、`同步中` | | `neutral` | `--an-muted` | 空态、停用、未上报、未知 | `暂无上报`、`停用` | | `ai` | 固定紫色 | AI 相关突出态 | AI 生成、模型动作 | 日志源列表遵循同一规则:`ok` 显示 success;`empty` 表示来源存在但还没有上报,显示 neutral;`missing` 表示期望的日志文件暂时不存在,显示 warning;`docker_unavailable` / `source_unavailable` 显示 danger。 ## 控制台运行时日志 控制台运行时错误由 [runtimeLogs.ts](/home/ray/dev/linkong/planet/frontend/src/admin/runtimeLogs.ts) 统一上报到 `/api/v1/system/logs/admin-client`。它只在控制台路由内启用,跳过 `/earth`、`/docs`、登录和注册页面,避免公开页面噪声进入控制台日志源。 [AdminErrorBoundary.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/components/AdminErrorBoundary.tsx) 捕获 React 渲染错误并复用同一上报函数;全局 `error` 和 `unhandledrejection` 也进入该通道。上报失败必须静默处理,不能因为日志系统异常再制造新的前端错误。 日志页通过 `/ws` 的 `logs_tail` channel 跟随日志增量;文件日志和数据库日志都由后端统一转换成行事件。新增日志源时优先接入后端 source registry 和 tail manager,不要在日志页写独立轮询器。 日志页默认进入“重复统计”视图,读取 `/api/v1/system/logs/observability/groups`,按 `fingerprint` 聚合 Earth、Admin 和服务端运行时上报;点击聚合项再读取 `/api/v1/system/logs/observability/groups/{fingerprint}/events` 展示发生明细。原始日志和审计日志仍保留为独立视图;只有原始日志视图允许通过 WebSocket 跟随。前端上报器会在短时间窗口内合并同一错误并提交 `occurrence_count`,后端同时写 `system_logs` 和 `observability_events` / `observability_event_groups`,所以日志页不要再按相同消息在浏览器端二次聚合。 数据源任务队列的“查看日志”入口跳转到 `/logs?source=system-db&search=task_id=`。后端数据库日志搜索索引必须把 JSON context 中的简单字段同时展开为 `key=value` 别名,例如 `task_id=26906`、`datasource_id=20`,这样历史任务日志不依赖重新执行任务也能被精确查到。 ## 当前共享组件 ### 1. `Scrollbar` 文件: - [Scrollbar.tsx](/home/ray/dev/linkong/planet/frontend/src/components/tactile-ui/Scrollbar.tsx) - [Tactile UI 组件库](/home/ray/dev/linkong/planet/docs/technical/zh/tactile-ui-components.md) 用途: - 控制台侧边栏这类普通内容容器 - 组件内部管理可见性、thumb 尺寸、拖拽和双轴 overflow 判定 当前约束: - 滚动条必须是浮层,不参与布局 - 无 overflow 时不应留下可见痕迹 - 真实滚动仍交给原生容器,只替换可见层和交互层 ### 2. `ScrollbarOverlay` 文件: - [ScrollbarOverlay.tsx](/home/ray/dev/linkong/planet/frontend/src/components/tactile-ui/ScrollbarOverlay.tsx) 用途: - Ant Table 这类内部已有滚动容器的区域 - 不接管滚动语义,只叠加新的滚动条可见层 当前使用场景: - 控制台数据源、采集数据、采集管理、日志、告警和 BGP 页面 ### 3. `TableScrollRegion` 文件: - [TableScrollRegion.tsx](/home/ray/dev/linkong/planet/frontend/src/components/tactile-ui/TableScrollRegion.tsx) 用途: - 为表格滚动区提供统一包裹层 - 后续新表格页优先复用,不要重复写“表格区域 + overlay scrollbar”样板 ### 4. `TactileButton` / `TactileSwitch` / `ControlGroup` 文件: - [Button.tsx](/home/ray/dev/linkong/planet/frontend/src/components/tactile-ui/Button.tsx) - [Switch.tsx](/home/ray/dev/linkong/planet/frontend/src/components/tactile-ui/Switch.tsx) - [ControlGroup.tsx](/home/ray/dev/linkong/planet/frontend/src/components/tactile-ui/ControlGroup.tsx) 用途: - 控制台全局工具按钮和详情页工具按钮 - icon-only + tooltip 的普通操作 - 保存、创建、确认、删除、停止等强意图操作 - 与文档主题滑块一致的紧凑开关 当前约束: - 默认按钮是白色触感按钮,通过外部投影表达轻微立体感 - 无歧义动作优先图标 + tooltip;保存这类强意图动作可保留文字 - 业务页面通过 props 和 CSS variables 调整,不要直接手写按钮核心样式 ### 5. `SegmentedControl` 文件: - [SegmentedControl.tsx](/home/ray/dev/linkong/planet/frontend/src/components/SegmentedControl/SegmentedControl.tsx) - [SegmentedControl.css](/home/ray/dev/linkong/planet/frontend/src/components/SegmentedControl/SegmentedControl.css) 用途: - 语言切换、主题切换、模式切换这类 2 到 3 项的分段控制器 - 需要保留滑块动画、激活态和紧凑按钮布局的设置项 - 当前 `/docs` 页底部语言切换与主题切换已经复用它 接口语义: - `options`:每个选项包含 `value`、`label`,可选 `icon`、`title` - `value`:当前激活值 - `onChange`:切换选项时回调 - `ariaLabel`:控制器可访问名称 - `className`:业务页面用于覆盖尺寸或局部样式 当前约束: - 组件自身负责滑块数量、位置和弹性动画 - 业务页面只传选项和状态,不要重复写私有 slider DOM - 颜色优先通过 CSS 变量覆盖,避免在业务组件里硬编码主题色 - 适合少量互斥选项,不适合用作长列表、导航菜单或表单下拉 ### 6. `MarkdownRenderer` 文件: - [MarkdownRenderer.tsx](/home/ray/dev/linkong/planet/frontend/src/components/MarkdownRenderer/MarkdownRenderer.tsx) 用途: - 渲染 `/docs` 的 Markdown 正文 - 支持标题、列表、引用、代码块、表格和基础行内格式 - 代码块和表格内部复用 `Scrollbar`,避免横向内容撑爆文档页 - 文档正文由后端 `/api/v1/docs/...` 按 Gatekeeper 权限返回;前端只渲染当前用户可见内容 当前约束: - 它不是完整 GitHub Markdown 引擎,只覆盖项目文档当前需要的语法 - 文档内部链接应通过 `transformLink` 转成 `/docs/:slug` - 标题锚点由 `getHeadingId` 注入,避免渲染器自己理解路由状态 ### 7. 控制台 UI primitives 文件: - [button.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/components/ui/button.tsx) - [dialog.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/components/ui/dialog.tsx) - [switch.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/components/ui/switch.tsx) 用途: - 全局工具按钮、详情页动作、确认弹窗和二元设置。 - 与 Tactile UI token 对齐,保持控制台内部控件尺寸、hover、disabled 和 dark mode 一致。 - 表格行内动作优先使用 icon button + tooltip/title,不重新引入独立操作菜单组件。 ## 当前状态来源 ### 1. 认证状态 文件: - [auth.ts](/home/ray/dev/linkong/planet/frontend/src/stores/auth.ts) 职责: - token - 当前用户 - Gatekeeper 权限组 - 登录/退出 `App.tsx` 用它判断是否进入登录页。`/docs` 仍是公开路由,但目录和正文由后端按 token 决定;未登录时只返回公开文档。 ### 2. AI 文件: - [AISettings.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/PlainResourcePages.tsx) 职责: - `/ai` 独立承载 LLM Provider、AI Tool 配置和测试台,不再放在 `/settings` 的系统配置 tabs 中 - `模型供应商` tab 管理默认 provider、模型、base URL、provider key、本地 `aiprovider` 代理和连接测试;provider 和模型输入使用可输入组合框,models.dev 目录停更时用户仍可手动填新 provider/model - `工具` tab 先通过下拉菜单选择工具,再管理对应配置;当前包含 WebSearch 和 OCR - WebSearch 配置包含 provider、搜索 key、base URL、超时、结果数和高级 provider 参数 - OCR 配置包含 provider、Base URL、API Key、模型/engine、语言、超时、文件大小上限和输出格式 - `测试台` tab 嵌入原 Playground 的真实会话、预设请求和 AI Provider 状态调试 - 页面复用 Settings 的单屏 tabs、panel card 和内部滚动样式 - AI Provider / WebSearch 的连接测试使用 `ConnectionTestInput`,连接器图标固定在 Base URL 输入框末端;WebSearch 未启用时,除开关外的配置项和测试入口都置灰 旧的 `/settings?tab=ai` 应跳转到 `/ai?tab=providers`。 旧的 `/playground` 应跳转到 `/ai?tab=playground`。 ### 3. 业务数据网关 目前 AI / 态势感知相关服务集中在: - [http-gateway.ts](/home/ray/dev/linkong/planet/frontend/src/services/situational-awareness/http-gateway.ts) - [port.ts](/home/ray/dev/linkong/planet/frontend/src/services/situational-awareness/port.ts) - [types.ts](/home/ray/dev/linkong/planet/frontend/src/services/situational-awareness/types.ts) 约束: - 页面不要直接散落拼 URL - 先通过 port/types 定义边界 - 再由 http/mock gateway 实现 ## 当前页面分层 ### 1. 仪表盘和摘要型页面 例如: - [Dashboard.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/Dashboard.tsx) 优先目标: - 页头稳定 - 摘要卡片先紧凑化 - 主工作区占据主要高度 ### 2. 表格型页面 例如: - [DataSources.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/PlainResourcePages.tsx) - [DataList.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/DataList.tsx) - [Users.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/Users.tsx) - [Settings.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/PlainResourcePages.tsx) 约束: - 优先内部滚动 - 不要让表格撑爆整页 - 新表格区域优先复用 `TableScrollRegion` / `ScrollbarOverlay` ### 数据源目录页 [DataSources.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/PlainResourcePages.tsx) 当前不再承担配置编辑职责,而是数据源目录和采集操作页。 当前页面边界: - 内置数据源和自定义数据源合并为 `UnifiedDataSource`。 - 列表展示类型、状态、最近运行、采集进度和操作。 - 点击名称打开只读抽屉。 - 抽屉中明确显示“内置数据源”或“自定义数据源”。 - endpoint、headers、config 只展示,不在这里编辑。 - 需要凭证的采集器提示用户到“采集管理 -> 采集器”维护。 这个边界很重要:后续不要把自定义数据源编辑、内置 endpoint 覆盖或凭证表单再塞回 `/datasources`。这些配置入口统一放在 `/collection-management?tab=collector_credentials`。 页面顶部的总进度区域新增 `采集中 N` 标签: - 仅在存在运行中采集任务时显示。 - 样式定义在 [index.css](/home/ray/dev/linkong/planet/frontend/src/index.css) 的 `data-source-bulk-toolbar__running-pill`。 - 点击后打开 `采集中任务` Modal。 - Modal 内展示每个运行任务的阶段、进度、已处理/总数。 这个标签和其他状态标签同排,但通过 hover、蓝色描边和箭头表示可交互,不应改成普通 Tag。 ### 采集器设置页 [Settings.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/PlainResourcePages.tsx) 会按路由进入三种模式:`/settings` 是系统设置,`/earth-content` 是智能星球内容,`/collection-management` 是采集管理。`collector_credentials` tab 当前在 `/collection-management` 下显示为“采集器”。 `/settings` 的“系统显示”分区包含 `演示模式` 开关。开启后,智能星球的 OOBE 会忽略“已有当前采集数据”和本地“先浏览”临时跳过状态,直接展示初始化引导;该开关仅用于演示/验收流程,不改变数据源、采集队列或智能星球内容资源配置。 当前页面边界: - 下拉框选择所有内置采集器。 - 下拉框右侧只有一个插头图标按钮,用于健康检查。 - 状态标签在选择器下方展示 `未检查` / `可用` / `不可用`。 - 需要凭证的采集器将凭证卡片放在基础配置上方。 - 不需要凭证的采集器只显示基础配置:endpoint、默认 endpoint、请求头、timeout、retry。 - `BarentsWatch AIS` 使用专用凭证表单。 连接图标使用内联 `PlugConnectIcon`,视觉语义来自 Tabler `plug-connected`。后续如果控制台重写图标体系,应迁移到 Tabler Icons,而不是继续使用 Ant Design 刷新图标表达连接。 `Client Secret` 的表单语义: - 已配置时,输入框显示脱敏 preview。 - 聚焦且当前值等于 preview 时清空,方便输入新 secret。 - 保存时如果值仍等于 preview,提交空值表示保留原 secret。 - 不再提供单独的“清除当前 secret”复选框。 凭证教程 Modal: - `GET /api/v1/settings/credential-guides/{provider}` 读取教程。 - `POST /generate` 调用 AI Provider 重新生成教程。 - `POST /reset` 恢复默认教程。 - Modal 使用 `MarkdownRenderer` 渲染教程正文。 相关后端设计见: - [数据源、采集器设置与连接验证](/home/ray/dev/linkong/planet/docs/technical/zh/datasource-collector-settings-connectivity.md) ### 智能星球内容页 `/earth-content` 复用 [Settings.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/PlainResourcePages.tsx) 的单屏 tab 容器,但页面责任与系统设置分离: - `电视直播` 迁移原直播源配置,继续管理 Earth 媒体面板内容源。 - `国界精度` 管理 Earth 静态国界资产:provider 状态、低精 fallback、高精 manifest/PMTiles、源配置 JSON 和构建动作。 - `地球底图`、`图层资源`、`三维素材`、`新闻锚点策略` 是占位页,只显示模块待接入,不造假接口或假数据。 系统级 `/settings` 不应再新增 Earth 体验资源或采集生命周期 tab;采集相关入口属于 `/collection-management`,Earth 展示资源属于 `/earth-content`。 ### 3. 复杂工作区页面 例如: - [BGP.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/PlainResourcePages.tsx) - [Playground.tsx](/home/ray/dev/linkong/planet/frontend/src/admin/pages/PlainResourcePages.tsx) 约束: - Tabs 里的内容不能套同一套高度逻辑 - 表格 tab、Markdown tab、配置 tab 要各自定义滚动责任 - AI 结果区、长文本区优先保证最小可读高度 ## 当前布局约束 这些原则已经在项目里反复验证过: 1. 父容器高度链要闭合 2. `min-height: 0` 不能漏 3. overflow 责任必须明确 4. 不要用 `overflow: hidden` 掩盖结构问题 5. 不要为了摘要卡完整显示去压缩主工作区 6. 自定义滚动条必须是浮层,不得挤压内容宽度 详细经验见: - [前端布局指南](/home/ray/dev/linkong/planet/docs/technical/zh/frontend-layout-guidelines.md)