594 lines
12 KiB
Markdown
594 lines
12 KiB
Markdown
# 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 数据格式
|
||
|
||
#### 折线图 / 柱状图数据格式
|
||
|
||
```typescript
|
||
{
|
||
xAxis: string[] // X 轴数据(时间、类别等)
|
||
series: Array<{
|
||
name: string // 系列名称
|
||
data: number[] // Y 轴数据
|
||
color?: string // 自定义颜色(可选)
|
||
}>
|
||
}
|
||
```
|
||
|
||
#### 饼图 / 环形图数据格式
|
||
|
||
```typescript
|
||
{
|
||
data: Array<{
|
||
name: string // 数据项名称
|
||
value: number // 数据值
|
||
color?: string // 自定义颜色(可选)
|
||
}>
|
||
}
|
||
```
|
||
|
||
### 图表类型说明
|
||
|
||
| 类型 | 适用场景 | 数据维度 |
|
||
|------|---------|---------|
|
||
| line | 趋势展示、时序数据、性能监控 | 多系列、时间轴 |
|
||
| bar | 对比分析、排名展示、统计数据 | 多系列、分类轴 |
|
||
| pie | 占比分析、分布展示 | 单维度、百分比 |
|
||
| ring | 占比分析(带中心文字) | 单维度、百分比 |
|
||
|
||
## 使用示例
|
||
|
||
### 折线图
|
||
|
||
```jsx
|
||
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}
|
||
/>
|
||
```
|
||
|
||
### 柱状图
|
||
|
||
```jsx
|
||
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}
|
||
/>
|
||
```
|
||
|
||
### 饼图
|
||
|
||
```jsx
|
||
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}
|
||
/>
|
||
```
|
||
|
||
### 环形图
|
||
|
||
```jsx
|
||
const ringData = {
|
||
data: [
|
||
{ name: '在线', value: 85 },
|
||
{ name: '离线', value: 15 },
|
||
],
|
||
}
|
||
|
||
<ChartPanel
|
||
type="ring"
|
||
title="在线率"
|
||
data={ringData}
|
||
height={200}
|
||
/>
|
||
```
|
||
|
||
### 自定义 ECharts 配置
|
||
|
||
```jsx
|
||
<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 使用
|
||
|
||
```jsx
|
||
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 结构层级
|
||
|
||
```html
|
||
<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 配置说明
|
||
|
||
### 折线图默认配置
|
||
|
||
```javascript
|
||
{
|
||
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 },
|
||
})),
|
||
}
|
||
```
|
||
|
||
### 柱状图默认配置
|
||
|
||
```javascript
|
||
{
|
||
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 },
|
||
})),
|
||
}
|
||
```
|
||
|
||
### 饼图默认配置
|
||
|
||
```javascript
|
||
{
|
||
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)',
|
||
},
|
||
},
|
||
},
|
||
],
|
||
}
|
||
```
|
||
|
||
### 环形图默认配置
|
||
|
||
```javascript
|
||
{
|
||
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. 根据 `type` 和 `data` 生成配置项
|
||
4. 调用 `setOption()` 渲染图表
|
||
|
||
### 更新流程
|
||
|
||
1. 当 `type`、`data`、`option` 变化时触发 `useEffect`
|
||
2. 复用已有的 ECharts 实例
|
||
3. 重新生成配置项并调用 `setOption()` 更新图表
|
||
|
||
### 响应式处理
|
||
|
||
1. 监听 `window.resize` 事件
|
||
2. 调用 `chartInstance.resize()` 自动调整图表尺寸
|
||
3. 组件卸载时移除事件监听并销毁 ECharts 实例
|
||
|
||
```javascript
|
||
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 容器
|
||
|
||
### 自定义样式示例
|
||
|
||
```css
|
||
/* 修改标题样式 */
|
||
.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 库,确保已安装:
|
||
|
||
```bash
|
||
npm install echarts
|
||
# 或
|
||
yarn add echarts
|
||
```
|
||
|
||
导入方式:
|
||
|
||
```javascript
|
||
import * as echarts from 'echarts'
|
||
```
|
||
|
||
## 示例数据结构参考
|
||
|
||
### 性能监控数据
|
||
|
||
```javascript
|
||
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',
|
||
},
|
||
],
|
||
}
|
||
```
|
||
|
||
### 状态分布数据
|
||
|
||
```javascript
|
||
const statusData = {
|
||
data: [
|
||
{ name: '运行中', value: 45, color: '#52c41a' },
|
||
{ name: '已停止', value: 20, color: '#8c8c8c' },
|
||
{ name: '错误', value: 5, color: '#ff4d4f' },
|
||
{ name: '待部署', value: 30, color: '#faad14' },
|
||
],
|
||
}
|
||
```
|
||
|
||
### 区域分布数据
|
||
|
||
```javascript
|
||
const regionData = {
|
||
xAxis: ['华东', '华南', '华北', '西南', '西北'],
|
||
series: [
|
||
{
|
||
name: '服务器数量',
|
||
data: [120, 80, 95, 65, 45],
|
||
color: '#1677ff',
|
||
},
|
||
],
|
||
}
|
||
```
|