B站视频内容智能分析系统(九):React 前端与管理面板

系列文章目录

B站视频内容智能分析系统(一):项目介绍与架构设计

B站视频内容智能分析系统(二):Docker Compose 一键部署

B站视频内容智能分析系统(三):B站视频自动采集

B站视频内容智能分析系统(四):语音转写三级回退

B站视频内容智能分析系统(五):LLM 内容精炼与多域分类

B站视频内容智能分析系统(六):Text-to-SQL 结构化查询

B站视频内容智能分析系统(七):RAG 语义检索

B站视频内容智能分析系统(八):Router Agent 智能路由

B站视频内容智能分析系统(九):React 前端与管理面板

文章目录

  • 系列文章目录
  • 前言
  • 一、整体架构
    • [1. 技术栈](#1. 技术栈)
    • [2. 双视图设计](#2. 双视图设计)
    • [3. 组件清单](#3. 组件清单)
  • 二、对话视图
    • [1. 消息组件](#1. 消息组件)
    • [2. 路由标签](#2. 路由标签)
    • [3. SQL 和来源展示](#3. SQL 和来源展示)
  • 三、斜杠命令
    • [1. 命令列表](#1. 命令列表)
    • [2. 结构化展示](#2. 结构化展示)
  • 四、管理面板
    • [1. 采集触发](#1. 采集触发)
    • [2. Cookie 管理](#2. Cookie 管理)
    • [3. GPU 转录](#3. GPU 转录)
    • [4. 查询日志](#4. 查询日志)
    • [5. 服务监控](#5. 服务监控)
  • 五、UP主管理
    • [1. 添加 UP主](#1. 添加 UP主)
    • [2. 导入导出](#2. 导入导出)
  • [六、Nginx 反向代理](#六、Nginx 反向代理)
  • [七、Docker SDK 容器触发](#七、Docker SDK 容器触发)
  • 总结

前言

前面八篇把后端的采集、转写、精炼、查询、路由全部讲完了。这篇来讲用户直接看到的部分------React 前端和管理面板。

前端的设计目标是一个页面搞定所有事:既能自然语言问答,又能管理采集任务、查看系统状态。所以我做了双视图设计------顶部 Tab 切换"对话"和"管理面板",不需要页面跳转。

一、整体架构

1. 技术栈

复制代码
React 18 + TypeScript + Tailwind CSS + Vite
  • React 18:函数组件 + Hooks,没用 Redux(状态不复杂)
  • TypeScript:类型安全,API 响应有明确的 interface 定义
  • Tailwind CSS:原子化 CSS,写样式快
  • Vite:开发服务器 + 构建,HMR 秒级刷新
  • Axios:HTTP 请求,2 分钟超时(LLM 查询可能很慢)

2. 双视图设计

复制代码
┌──────────────────────────────────────────┐
│  智能内容分析系统     [对话] [管理面板]     │
├──────────────────────────────────────────┤
│                                          │
│  对话视图                  管理面板视图    │
│  ┌────────────┬────────┐  ┌────────────┐ │
│  │            │  侧    │  │ [采集]     │ │
│  │  聊天区域  │  边    │  │ [GPU转录]  │ │
│  │            │  栏    │  │ [查询日志] │ │
│  ├────────────┤        │  │ [服务监控] │ │
│  │  输入框    │        │  │            │ │
│  └────────────┴────────┘  └────────────┘ │
└──────────────────────────────────────────┘

状态管理很简单,一个 activeTab 控制显示哪个视图:

tsx 复制代码
type MainTab = 'chat' | 'admin';
const [activeTab, setActiveTab] = useState<MainTab>('chat');

3. 组件清单

组件 职责
App.tsx 应用外壳,Tab 切换 + 侧边栏
ChatInput 输入框,支持斜杠命令和域选择
ChatMessage 消息气泡,路由标签 + SQL + 推理 + 来源
QuickView 斜杠命令结果的结构化展示
StatusPanel 右侧边栏(数据概览 + 快捷问题 + 状态)
AdminPanel 管理面板容器,4 个子 Tab
MonitorTrigger 采集触发 + Cookie 管理
UpManager UP主添加/删除/列表
GpuTranscribe GPU 转录 + 云 ASR 转写
QueryLog 查询日志分页列表
SystemMetrics 服务监控仪表盘

二、对话视图

1. 消息组件

每条消息是一个 ChatMessage 组件,支持展示多种信息:

tsx 复制代码
interface Message {
  id: string;
  role: 'user' | 'assistant';
  content: string;            // Markdown 格式的回答
  routeType?: string;         // structured | semantic | hybrid
  sql?: string;               // SQL 语句(可展开)
  sqlResult?: any[];          // SQL 查询结果(表格)
  reasoning?: string;         // 推理过程(可折叠)
  responseTime?: number;      // 响应时间
  sources?: SourceItem[];     // 来源引用
  quickView?: { ... };        // 斜杠命令结果
}

2. 路由标签

每条 AI 回答前面有一个彩色标签,标识走了哪个通道:

tsx 复制代码
// 路由标签颜色
const routeColors = {
  structured: 'bg-purple-100 text-purple-800',   // 紫色
  semantic: 'bg-green-100 text-green-800',       // 绿色
  hybrid: 'bg-orange-100 text-orange-800',       // 橙色
};

const routeLabels = {
  structured: '结构化查询',
  semantic: '语义检索',
  hybrid: '混合查询',
};

用户可以一眼看出这个问题的回答来自哪个通道。

3. SQL 和来源展示

结构化查询会展示 SQL 语句和查询结果表格:

tsx 复制代码
{message.sql && (
  <details className="mt-2">
    <summary className="cursor-pointer text-xs text-gray-500">
      查看 SQL
    </summary>
    <pre className="mt-1 p-2 bg-gray-50 rounded text-xs overflow-x-auto">
      {message.sql}
    </pre>
  </details>
)}

{message.sqlResult && (
  <ResultTable data={message.sqlResult} />
)}

语义查询会展示来源引用(来自哪些视频):

tsx 复制代码
{message.sources && message.sources.length > 0 && (
  <div className="mt-2 text-xs text-gray-500">
    来源:{message.sources.map(s =>
      `[${s.up_name}] ${s.title}`
    ).join(', ')}
  </div>
)}

三、斜杠命令

1. 命令列表

输入框支持以 / 开头的快捷命令:

命令 功能
/status 系统状态(Router / SQL / RAG 可用性)
/up_list 所有 UP主列表及视频数
/recent 最近采集的 10 个视频
/categories 31 个情感分类统计
/sql [问题] 强制走 Text-to-SQL
/rag [问题] 强制走 RAG
/clear 清空对话
/help 显示帮助

处理逻辑:

tsx 复制代码
const handleSend = async (input: string) => {
  if (input.startsWith('/')) {
    const response = await handleSlashCommand(input);
    setMessages(prev => [...prev, response]);
  } else {
    const result = await chat(input);
    // ...
  }
};

2. 结构化展示

斜杠命令的结果不是普通文本,而是通过 QuickView 组件做结构化展示:

  • /status:三色状态卡片(绿=正常、红=异常、灰=未知)
  • /up_list:UP主卡片列表(头像 + 名称 + 视频数)
  • /recent:视频列表(标题 + UP主 + 分类标签 + 时长)
  • /categories:水平条形图(分类名 + 视频数 + 百分比)
tsx 复制代码
// /categories 条形图
{categories.map(cat => (
  <div key={cat.name} className="flex items-center gap-2">
    <span className="w-20 text-xs text-right">{cat.name}</span>
    <div className="flex-1 bg-gray-100 rounded-full h-4">
      <div
        className="bg-blue-500 h-4 rounded-full"
        style={{ width: `${(cat.count / max) * 100}%` }}
      />
    </div>
    <span className="text-xs w-12">{cat.count}</span>
  </div>
))}

四、管理面板

1. 采集触发

管理面板的第一个 Tab 是采集触发,主要功能:

  • 状态指示器:显示采集状态(空闲/运行中/完成/失败)
  • UP主多选:下拉选择要采集的 UP主
  • 参数设置:最大视频数、全量扫描复选框
  • 触发按钮:一键启动采集
  • 实时日志:终端风格的日志窗口,运行中每 5 秒自动刷新
tsx 复制代码
// 运行中时自动轮询
useEffect(() => {
  if (status?.status === 'running') {
    pollRef.current = setInterval(fetchStatus, 5000);
  }
  return () => {
    if (pollRef.current) clearInterval(pollRef.current);
  };
}, [status?.status]);

B站 Cookie 管理是可折叠的面板:

  • 保存 Cookie:粘贴 Netscape 格式的内容
  • 测试 Cookie:调用 B站 API 验证有效性
  • 删除 Cookie:清除已保存的 Cookie

状态灯指示 Cookie 状态:

  • 🟢 已配置 + 有效
  • 🔴 已过期
  • 🔴 未配置
tsx 复制代码
// Cookie 状态灯
<div className={`w-3 h-3 rounded-full ${
  cookieValid ? 'bg-green-500' : 'bg-red-500'
} ${isRunning ? 'animate-pulse' : ''}`} />

采集前会自动预检 Cookie,如果未配置或已过期,采集按钮会被禁用。

3. GPU 转录

分成两个区域:

GPU 转录(开发机)

  • GPU 状态卡片(CUDA 可用性、显存、PyTorch 版本)
  • 模型/设备选择
  • 进度条 + 实时日志

云 ASR 转写(NAS)

  • 开关控制(启用/禁用 ASR)
  • 月度预算设置 + 用量进度条
  • 手动触发按钮
  • 最近转写记录

4. 查询日志

展示所有历史查询记录:

  • 统计卡片:总查询数、平均响应时间、各路由类型分布
  • 查询表格:问题、路由类型(彩色标签)、响应时间、查询时间
  • 过滤 + 分页:按路由类型过滤,每页 15 条

5. 服务监控

实时展示各容器的运行状态:

  • 容器状态卡片:状态灯 + 内存使用进度条 + CPU 使用率 + 端口
  • 知识库指标:向量文档块数、视频总数、总查询数
  • 查询类型分布:水平条形图(结构化/语义/混合占比)

自动刷新(默认 30 秒),也可以手动刷新。

五、UP主管理

1. 添加 UP主

在采集触发页面底部,可以添加新的 UP主:

  1. 粘贴 B站链接(主页链接或视频链接)

  2. 选择 Whisper 模型(small / medium)

  3. 选择内容域(情感 / 求职)

  4. 点击"解析"→ 展示预览卡片

  5. 点击"确认添加"→ 生成 YAML 配置

    支持两种链接格式:

后端会调 B站 API 获取 UP主 信息(名称、UID、头像),前端展示预览卡片让用户确认。

2. 导入导出

UP主数据支持 ZIP 打包导入导出:

导出 :把所有 UP主 的配置 + 元数据 + 向量 + 转写文本打包成 ZIP

导入:上传 ZIP 文件,一键恢复所有 UP主 数据

这个功能用于跨环境迁移------在开发机上采集的数据,打包后导入到 NAS:

复制代码
导出 ZIP 内容:
├── configs/          # UP主 YAML 配置
├── metadata/         # DuckDB 导出的元数据
├── transcripts/      # 转写文本文件
└── manifest.json     # 版本和校验信息

Nginx 配置了 client_max_body_size 500m,支持大文件上传。

六、Nginx 反向代理

前端容器同时承担 Nginx 反向代理的职责。所有 API 请求都通过 Nginx 转发到后端:

nginx 复制代码
# /api/ → Router Agent
location /api/ {
    client_max_body_size 500m;
    set $upstream_router http://router-agent:8000;
    proxy_pass $upstream_router;
    proxy_read_timeout 120s;
}

# /query → Text-to-SQL(向后兼容)
location /query {
    set $upstream_t2s http://text-to-sql:8010;
    proxy_pass $upstream_t2s;
}

# 静态资源缓存 1 年
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

关键配置:

  • resolver 127.0.0.11:Docker 内置 DNS,用变量避免容器重建后 IP 变化导致 502
  • client_max_body_size 500m:支持 UP主导入的大文件上传
  • proxy_read_timeout 120s:LLM 查询可能需要较长时间

API 层(api.ts)的超时也配合设置为 2 分钟:

typescript 复制代码
const api = axios.create({
  baseURL: '/api',
  timeout: 120000,  // 2分钟(LLM 查询可能很慢)
});

七、Docker SDK 容器触发

前端触发采集不是直接调 bilibili-monitor 的 API(它是批处理容器,没有常驻 API),而是通过 Router Agent 的 Docker SDK 动态启动新容器:

复制代码
前端 POST /api/trigger_monitor {up_names: ["桃姐"], full_scan: true}
  ↓
Router Agent(monitor_trigger.py)
  ↓ Docker SDK
  docker run --rm content-analysis-system-bilibili-monitor \
    python src/monitor_all.py --up 桃姐 --full-scan
  ↓
前端 GET /api/trigger_status(每5秒轮询)
  → {status: "running", logs: [...]}
  → {status: "completed", exit_code: 0}

Router Agent 挂载了 Docker socket(/var/run/docker.sock),所以可以在容器内控制宿主机的 Docker daemon。

前端的轮询逻辑:

tsx 复制代码
useEffect(() => {
  if (status?.status === 'running') {
    pollRef.current = setInterval(fetchStatus, 5000);
  } else {
    if (pollRef.current) clearInterval(pollRef.current);
  }
  return () => {
    if (pollRef.current) clearInterval(pollRef.current);
  };
}, [status?.status]);

运行中时 5 秒轮询一次,完成后停止轮询。日志窗口自动滚动到最新行。

总结

前端用 React + TypeScript + Tailwind CSS 构建,双视图设计(对话 + 管理面板)让用户在一个页面内完成所有操作。对话视图支持自然语言问答和斜杠命令,每条回答附带路由标签、SQL 语句和来源引用。管理面板集成了采集触发、Cookie 管理、GPU 转录、查询日志和服务监控。Nginx 反向代理统一转发 API 请求,Docker SDK 实现容器的动态触发。下一篇是这个系列的最后一篇------踩坑记录与性能优化。

相关推荐
Cutecat_4 小时前
视频字幕处理工具横向:提取模式 vs 编辑模式,该如何选择
android·前端·ios·语音识别
qq_422152575 小时前
PDF 加水印工具怎么选?2026 年文档版权保护方案对比
前端·pdf·github
kyriewen5 小时前
手写 Promise.all、race、any:不到 30 行代码,解决并发异步的所有姿势
前端·javascript·面试
brucelee1866 小时前
OpenClaw 浏览器控制(Chrome MCP)完整教程
前端·chrome
ct9786 小时前
React 状态管理方案深度对比
开发语言·前端·react
胡志辉的博客6 小时前
深入浅出理解浏览器事件循环:从一道输出题讲到 Chrome 源码
前端·javascript·chrome·chromium·event loop
代码不加糖6 小时前
js中不会冒泡的事件有哪些?
前端·javascript·vue.js
懂懂tty7 小时前
Vue2与Vue3之间API差异
前端·javascript·vue.js
AI焦点7 小时前
跨越协议鸿沟:Tool Use状态机从Anthropic到OpenAI兼容体系的适配要点
前端·人工智能