GB T28181 开源日记[3]:使用 React 组件构建数据面板
ixugo. edited this page 2025-02-10 10:04:36 +08:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

使用 React 组件构建数据面板

完善导航

按照登录页的方式,我们在 shadcn/ui 官网中找到导航组件,拷贝源代码,在 routes/home.tsx 中粘贴。

并使用 react-routerOutlet 组件实现路由嵌套,非常适合点击不同的菜单按钮,跳转不同的路由这种场景。

导航可以使用

image-20250108005342559

app/routes.ts 中定义首页,使用layout ,布局路由为其子级创建新的嵌套,但它们不会向 URL 添加任何分段。它就像根路由,但可以在任何级别添加它们。

layout("routes/home.tsx", [
  route("home", "routes/dashboard/dashboard.tsx")
  // route("devices" ...)
  // route("channels" ...)
]),

完善数据面板

创建并编辑文件 routes/dashboard/dashboard.tsx

按照两行三列的布局,依次是

  • CPU 面积图,设备统计饼图,网络 IO 折线图
  • 内存使用面积图,流负载信息柱状图,磁盘使用条形图

我们在 DashboardView 的父组件中获取数据,将数据传递到子组件 CPUBoxCountBoxNetworkBox 等等。

依次创建

  • routes/dashboard/cpu.tsx CPU 面积图
  • routes/dashboard/network.tsx 网络 IO 折线图
  • routes/dashboard/disk.tsx 磁盘使用条形图
  • routes/dashboard/memory.tsx 内存使用面积图
  • routes/dashboard/count.tsx 设备统计饼图
  • routes/dashboard/load.tsx 流负载信息柱状图

同样在 shadcn/ui 网站找到对应的图标组件,拷贝源代码到对应的目录下,微调达到效果,类似的细节不再赘述。

如此数据面板就完成了,代码结构清晰,简单,尝试看看下方的源代码?

在源代码中将组件作为数组,使用 map 遍历数组,外层包裹自定义的 Cardbox 组件,是为了定制些统一的样式。

export default function DashboardView() {
  // 使用 react-query 固定间隔获取一次服务端状态信息
  const query = useQuery({
    queryKey: ["dashboard"],
    queryFn: FindStats,
    refetchInterval: 5000,
    throwOnError: (error, query) => {
      return false;
    },
  });

  return (
    <div className="flex flex-col h-full ml-1">
      <div className="flex flex-1">
        {[
          // cpu 面积图
          <CPUBox data={query.data?.data.cpu ?? []} />,
          // 设备统计饼图
          <CountBox />,
          // 网络 IO 折线图
          <NetworkBox data={query.data?.data.net ?? []} />,
        ].map((item, index) => (
          <Cardbox key={index} className="bg-blue-200">
            {item}
          </Cardbox>
        ))}
      </div>
      <div className="flex flex-1">
        {[
          // 内存使用面积图
          <MemoryBox data={query.data?.data.mem ?? []} />,
          // 流负载信息柱状图
          <LoadBox />,
          // 磁盘使用条形图
          <DiskBox data={query.data?.data.disk ?? []} />,
        ].map((item, index) => (
          <Cardbox key={index} className="bg-blue-200">
            {item}
          </Cardbox>
        ))}
      </div>
    </div>
  );
}

技术回顾

react router v7

回顾一下我们目前用到的三种路由配置函数

  • index: 默认子路由,访问其父级路由时默认显示。
  • layout: 搭配 Outlet 做布局路由,比如每个页面都有共同的菜单导航
  • route: 定义页面路由,搭配 Link ,redirect 组件或 useNavigate Hook 达成路由跳转。

react query v5

回顾一下我们目前用到的查询方式 useQuery

  • queryKey: 查询数据的唯一标识,如果查询数据时,使用了分页/过滤等条件,这些条件也应该附加到 queryKey 中,其类型是数组类型,顺序很重要!! 但如果数组中包含 {} map 对象,map 内的元素无论什么顺序,视为相等。react-query 会将查询到的数据缓存起来(缓存时间取决于配置),网页加载时会根据 queryKey 优先读取缓存,使页面体验更流畅。当 key 发生更改时,比如分页条件变化,查询就会自动重新获取数据(取决于 staleTime 设置)。
  • queryFn: 查询请求函数。
  • refetchInterval: 重新获取数据的间隔时间(毫秒)
  • throwOnError: 抛出错误,建议设置为函数,它将传递错误和查询,并且它应该返回一个布尔值,指示是否在错误边界中显示错误( true )或将错误返回为状态( false )。

shadcn/ui

还有一些细节的处理将在后续的文章中同步,期望文章更快进入 GB28181 信令设计部分。

后续的文章也会更偏向服务端开发,数据库设计,GB/T28181 信令,注册/注销/Catalog....

参考

[react router 官方文档,Outlet 使用说明](https://reactrouter.com/start/framework/routing)

[react query 官方文档,useQuery 使用说明](https://tanstack.com/query/latest/docs/framework/react/reference/useQuery#usequery)