nex_design/docs/components/ChartPanel.md

12 KiB
Raw Blame History

ChartPanel 组件

组件说明

图表面板组件,基于 ECharts 封装,用于展示数据可视化图表。支持折线图、柱状图、饼图、环形图等多种图表类型,适合在仪表盘、监控面板、数据分析页面中使用。

组件位置

src/components/ChartPanel/ChartPanel.jsx
src/components/ChartPanel/ChartPanel.css

参数说明

参数名 类型 必填 默认值 说明
type string 'line' 图表类型line/bar/pie/ring
title string - 图表标题
data ChartData - 图表数据
height number 200 图表高度(像素)
option object {} 自定义 ECharts 配置项
className string '' 自定义类名

ChartData 数据格式

折线图 / 柱状图数据格式

{
  xAxis: string[]        // X 轴数据(时间、类别等)
  series: Array<{
    name: string         // 系列名称
    data: number[]       // Y 轴数据
    color?: string       // 自定义颜色(可选)
  }>
}

饼图 / 环形图数据格式

{
  data: Array<{
    name: string         // 数据项名称
    value: number        // 数据值
    color?: string       // 自定义颜色(可选)
  }>
}

图表类型说明

类型 适用场景 数据维度
line 趋势展示、时序数据、性能监控 多系列、时间轴
bar 对比分析、排名展示、统计数据 多系列、分类轴
pie 占比分析、分布展示 单维度、百分比
ring 占比分析(带中心文字) 单维度、百分比

使用示例

折线图

import ChartPanel from '../components/ChartPanel/ChartPanel'

const lineData = {
  xAxis: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'],
  series: [
    {
      name: 'CPU 使用率',
      data: [30, 45, 65, 50, 70, 55],
      color: '#1677ff',
    },
    {
      name: '内存使用率',
      data: [20, 35, 55, 45, 60, 50],
      color: '#52c41a',
    },
  ],
}

<ChartPanel
  type="line"
  title="性能监控"
  data={lineData}
  height={300}
/>

柱状图

const barData = {
  xAxis: ['周一', '周二', '周三', '周四', '周五'],
  series: [
    {
      name: '新增用户',
      data: [120, 200, 150, 180, 220],
      color: '#1677ff',
    },
    {
      name: '活跃用户',
      data: [80, 150, 120, 140, 180],
      color: '#52c41a',
    },
  ],
}

<ChartPanel
  type="bar"
  title="用户统计"
  data={barData}
  height={250}
/>

饼图

const pieData = {
  data: [
    { name: '运行中', value: 45, color: '#52c41a' },
    { name: '已停止', value: 20, color: '#8c8c8c' },
    { name: '错误', value: 5, color: '#ff4d4f' },
    { name: '待部署', value: 30, color: '#faad14' },
  ],
}

<ChartPanel
  type="pie"
  title="状态分布"
  data={pieData}
  height={250}
/>

环形图

const ringData = {
  data: [
    { name: '在线', value: 85 },
    { name: '离线', value: 15 },
  ],
}

<ChartPanel
  type="ring"
  title="在线率"
  data={ringData}
  height={200}
/>

自定义 ECharts 配置

<ChartPanel
  type="line"
  data={lineData}
  option={{
    grid: {
      left: '5%',
      right: '5%',
      bottom: '10%',
    },
    tooltip: {
      trigger: 'axis',
      backgroundColor: 'rgba(0, 0, 0, 0.8)',
    },
    xAxis: {
      axisLabel: {
        rotate: 45,
      },
    },
  }}
/>

配合 SideInfoPanel 使用

import SideInfoPanel from '../components/SideInfoPanel/SideInfoPanel'
import ChartPanel from '../components/ChartPanel/ChartPanel'

<SideInfoPanel
  sections={[
    {
      key: 'performance',
      title: '性能监控',
      icon: <LineChartOutlined />,
      content: (
        <>
          <ChartPanel
            type="line"
            title="CPU 使用率"
            data={cpuData}
            height={200}
          />
          <ChartPanel
            type="line"
            title="内存使用率"
            data={memoryData}
            height={200}
          />
        </>
      ),
    },
    {
      key: 'distribution',
      title: '状态分布',
      icon: <PieChartOutlined />,
      content: (
        <>
          <ChartPanel
            type="ring"
            title="在线状态"
            data={statusData}
            height={200}
          />
          <ChartPanel
            type="bar"
            title="区域分布"
            data={regionData}
            height={200}
          />
        </>
      ),
    },
  ]}
/>

DOM 结构层级

<div class="chart-panel">

  <!-- 图表标题(可选) -->
  {title && (
    <div class="chart-panel-title">
      {title}
    </div>
  )}

  <!-- ECharts 容器 -->
  <div
    ref={chartRef}
    class="chart-panel-chart"
    style="height: 200px"
  >
    <!-- ECharts 实例挂载点 -->
  </div>

</div>

ECharts 配置说明

折线图默认配置

{
  tooltip: {
    trigger: 'axis',
    backgroundColor: 'rgba(0, 0, 0, 0.7)',
  },
  legend: {
    bottom: 0,
    left: 'center',
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '15%',
    containLabel: true,
  },
  xAxis: {
    type: 'category',
    data: data.xAxis,
    boundaryGap: false,
  },
  yAxis: {
    type: 'value',
  },
  series: data.series.map(s => ({
    name: s.name,
    type: 'line',
    data: s.data,
    smooth: true,
    itemStyle: { color: s.color },
  })),
}

柱状图默认配置

{
  tooltip: {
    trigger: 'axis',
    axisPointer: { type: 'shadow' },
  },
  legend: {
    bottom: 0,
    left: 'center',
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '15%',
    containLabel: true,
  },
  xAxis: {
    type: 'category',
    data: data.xAxis,
  },
  yAxis: {
    type: 'value',
  },
  series: data.series.map(s => ({
    name: s.name,
    type: 'bar',
    data: s.data,
    itemStyle: { color: s.color },
  })),
}

饼图默认配置

{
  tooltip: {
    trigger: 'item',
    formatter: '{b}: {c} ({d}%)',
  },
  legend: {
    bottom: 0,
    left: 'center',
  },
  series: [
    {
      type: 'pie',
      radius: '70%',
      center: ['50%', '45%'],
      data: data.data.map(item => ({
        name: item.name,
        value: item.value,
        itemStyle: { color: item.color },
      })),
      emphasis: {
        itemStyle: {
          shadowBlur: 10,
          shadowOffsetX: 0,
          shadowColor: 'rgba(0, 0, 0, 0.5)',
        },
      },
    },
  ],
}

环形图默认配置

{
  tooltip: {
    trigger: 'item',
    formatter: '{b}: {c} ({d}%)',
  },
  legend: {
    bottom: 0,
    left: 'center',
  },
  series: [
    {
      type: 'pie',
      radius: ['50%', '70%'],  // 环形图特征:内外半径
      center: ['50%', '45%'],
      data: data.data.map(item => ({
        name: item.name,
        value: item.value,
        itemStyle: { color: item.color },
      })),
      label: {
        show: false,  // 环形图默认不显示标签
      },
      emphasis: {
        itemStyle: {
          shadowBlur: 10,
          shadowOffsetX: 0,
          shadowColor: 'rgba(0, 0, 0, 0.5)',
        },
      },
    },
  ],
}

组件生命周期

初始化流程

  1. 组件挂载时,通过 useRef 获取 DOM 容器
  2. 使用 echarts.init() 初始化 ECharts 实例
  3. 根据 typedata 生成配置项
  4. 调用 setOption() 渲染图表

更新流程

  1. typedataoption 变化时触发 useEffect
  2. 复用已有的 ECharts 实例
  3. 重新生成配置项并调用 setOption() 更新图表

响应式处理

  1. 监听 window.resize 事件
  2. 调用 chartInstance.resize() 自动调整图表尺寸
  3. 组件卸载时移除事件监听并销毁 ECharts 实例
useEffect(() => {
  const handleResize = () => {
    if (chartInstance.current) {
      chartInstance.current.resize()
    }
  }

  window.addEventListener('resize', handleResize)

  return () => {
    window.removeEventListener('resize', handleResize)
    if (chartInstance.current) {
      chartInstance.current.dispose()
    }
  }
}, [])

样式定制

组件提供以下 CSS 类名供自定义样式:

  • .chart-panel - 面板容器
  • .chart-panel-title - 图表标题
  • .chart-panel-chart - ECharts 容器

自定义样式示例

/* 修改标题样式 */
.chart-panel-title {
  font-size: 16px;
  font-weight: 600;
  color: #1677ff;
}

/* 修改面板背景 */
.chart-panel {
  background: #f5f5f5;
  border-radius: 8px;
  padding: 16px;
}

/* 修改图表容器 */
.chart-panel-chart {
  background: #ffffff;
}

使用场景

  1. 性能监控面板 - 展示 CPU、内存、网络等实时性能数据
  2. 数据分析仪表盘 - 展示业务指标、用户统计、销售数据
  3. 状态分布展示 - 展示系统状态、设备状态、任务状态的占比
  4. 趋势对比分析 - 展示多个指标的时序变化和对比

注意事项

  1. 数据格式

    • 确保数据格式与图表类型匹配
    • 折线图/柱状图使用 xAxis + series 格式
    • 饼图/环形图使用 data 数组格式
    • 数据更新时会自动重新渲染
  2. 图表高度

    • 默认高度 200px建议根据内容调整
    • 折线图/柱状图200-400px
    • 饼图/环形图200-300px
    • 避免高度过小导致显示不清
  3. 颜色使用

    • 可在数据中指定 color 属性自定义颜色
    • 不指定时使用 ECharts 默认配色
    • 建议使用语义化颜色(绿色=正常,红色=错误)
    • 同一页面保持配色风格一致
  4. 性能优化

    • 大数据量时考虑数据采样
    • 避免频繁更新图表(建议间隔 > 1s
    • 组件卸载时会自动销毁 ECharts 实例
    • 窗口 resize 时会自动调整图表尺寸
  5. 响应式

    • 图表会自动适应容器宽度
    • 窗口大小变化时自动 resize
    • 小屏幕时建议减小图表高度
  6. 自定义配置

    • 使用 option 参数传入自定义 ECharts 配置
    • 自定义配置会与默认配置深度合并
    • 可完全覆盖默认配置实现高度定制
  7. 标题使用

    • title 为可选参数
    • 在 SideInfoPanel 中使用时section 已有标题,可省略 ChartPanel 标题
    • 独立使用时建议添加标题增强可读性

配合使用的组件

  • SideInfoPanel - 侧边信息面板(推荐)
  • StatCard - 统计卡片(配合使用)
  • SplitLayout - 分栏布局
  • PageTitleBar - 页面标题栏

ECharts 依赖

本组件依赖 ECharts 库,确保已安装:

npm install echarts
# 或
yarn add echarts

导入方式:

import * as echarts from 'echarts'

示例数据结构参考

性能监控数据

const performanceData = {
  xAxis: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00'],
  series: [
    {
      name: 'CPU',
      data: [30, 45, 65, 50, 70, 55],
      color: '#1677ff',
    },
    {
      name: '内存',
      data: [20, 35, 55, 45, 60, 50],
      color: '#52c41a',
    },
  ],
}

状态分布数据

const statusData = {
  data: [
    { name: '运行中', value: 45, color: '#52c41a' },
    { name: '已停止', value: 20, color: '#8c8c8c' },
    { name: '错误', value: 5, color: '#ff4d4f' },
    { name: '待部署', value: 30, color: '#faad14' },
  ],
}

区域分布数据

const regionData = {
  xAxis: ['华东', '华南', '华北', '西南', '西北'],
  series: [
    {
      name: '服务器数量',
      data: [120, 80, 95, 65, 45],
      color: '#1677ff',
    },
  ],
}