Skip to content

Commit 08310cf

Browse files
authored
Merge pull request #53 from mayinrain/master
upd: 新增charts组件
2 parents 766bdc7 + d1ffc15 commit 08310cf

File tree

13 files changed

+523
-8
lines changed

13 files changed

+523
-8
lines changed

.vscode/settings.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77
],
88
// 每次保存的时候将代码按 eslint 格式进行修复
99
"editor.codeActionsOnSave": {
10-
// For ESLint
11-
"source.fixAll.eslint": true,
12-
// 文件保存时开启 stylelint 自动修复程序
13-
"source.fixAll.stylelint": true,
10+
"source.fixAll.eslint": "explicit",
11+
"source.fixAll.stylelint": "explicit"
1412
},
1513
// json 文件按 prettier 规范格式化
1614
"[json]": {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# BCharts
2+
提供通用的图表组件,支持时间范围选择和数据刷新。
3+
4+
## 组件注册
5+
6+
```js
7+
import { BCharts } from '@fesjs/traction-widget';
8+
app.use(BCharts);
9+
```
10+
11+
## 代码演示
12+
### 基础用法
13+
传入图表配置和数据获取方法,自动处理图表的渲染和更新。
14+
15+
--USE
16+
17+
--CODE
18+
19+
## 参数说明
20+
### BCharts Props
21+
| 属性 | 说明 | 类型 | 默认值 | 是否必须 |
22+
| ----- | ---------------------- | --------------------------------------- | -------- | -------- |
23+
| chartId | 图表DOM的id | string | - ||
24+
| config | 图表配置项 | ChartConfig | - ||
25+
| initialDays | 初始时间范围天数 | number | 7 ||
26+
27+
### ChartConfig 类型定义
28+
```ts
29+
interface BarStyle {
30+
color: string;
31+
borderColor: string;
32+
}
33+
34+
interface ChartConfig {
35+
// 图表标题
36+
title: string;
37+
// 数据项配置
38+
series: {
39+
field: string;
40+
name: string;
41+
itemStyle: BarStyle;
42+
}[];
43+
// 获取数据的方法,接收时间范围参数
44+
fetchData: (startTime: number, endTime: number) => Promise<any[]>;
45+
// x轴字段名
46+
xAxisField: string;
47+
// 自定义 tooltip 格式化函数
48+
tooltipFormatter?: (params: any[]) => string;
49+
}
50+
```
51+
52+
## 注意事项
53+
1. 组件会自动处理图表的初始化和销毁
54+
2. 时间范围变化时会自动重新获取数据并更新图表
55+
3. 支持自定义每个数据系列的样式
56+
4. 确保提供唯一的 chartId 以避免 DOM 冲突
57+
5. 可以通过 tooltipFormatter 自定义提示框的显示格式
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<template>
2+
<div class="chart-demo">
3+
<BCharts
4+
chart-id="demo-chart"
5+
:config="chartConfig"
6+
:initial-days="7"
7+
/>
8+
</div>
9+
</template>
10+
11+
<script setup lang="ts">
12+
import { BCharts } from '@fesjs/traction-widget';
13+
14+
const chartConfig = {
15+
title: '告警统计分析',
16+
series: [
17+
{
18+
field: 'critical',
19+
name: '严重告警',
20+
itemStyle: {
21+
color: '#FEEEEE',
22+
borderColor: '#FF4D4F'
23+
}
24+
},
25+
{
26+
field: 'major',
27+
name: '主要告警',
28+
itemStyle: {
29+
color: '#EDF2FF',
30+
borderColor: '#5384FF'
31+
}
32+
},
33+
{
34+
field: 'minor',
35+
name: '次要告警',
36+
itemStyle: {
37+
color: '#FFF4EB',
38+
borderColor: '#FF9900'
39+
}
40+
},
41+
{
42+
field: 'warning',
43+
name: '警告',
44+
itemStyle: {
45+
color: '#FFF3DC',
46+
borderColor: '#FAC017'
47+
}
48+
},
49+
{
50+
field: 'info',
51+
name: '信息',
52+
itemStyle: {
53+
color: '#D1F4E9',
54+
borderColor: '#00CB91'
55+
}
56+
}
57+
],
58+
xAxisField: 'date',
59+
fetchData: async (startTime: number, endTime: number) => {
60+
// 模拟异步数据获取
61+
return new Promise((resolve) => {
62+
setTimeout(() => {
63+
// 生成模拟数据
64+
const days = Math.floor((endTime - startTime) / (24 * 60 * 60 * 1000));
65+
const data = [];
66+
67+
for (let i = 0; i <= days; i++) {
68+
const date = new Date(startTime + i * 24 * 60 * 60 * 1000);
69+
data.push({
70+
date: date.toISOString().split('T')[0],
71+
critical: Math.floor(Math.random() * 10),
72+
major: Math.floor(Math.random() * 15),
73+
minor: Math.floor(Math.random() * 20),
74+
warning: Math.floor(Math.random() * 25),
75+
info: Math.floor(Math.random() * 30)
76+
});
77+
}
78+
79+
resolve(data);
80+
}, 1000);
81+
});
82+
}
83+
};
84+
</script>
85+
86+
<style scoped>
87+
.chart-demo {
88+
padding: 24px;
89+
background: #fff;
90+
border-radius: 4px;
91+
min-height: 500px;
92+
}
93+
</style>

docs/.vitepress/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export default defineConfig({
9494
{ text: 'BSearch', link: '/components/BSearch' },
9595
{ text: 'BDynamicForms', link: '/components/BDynamicForms'},
9696
{ text: 'BMetricTip', link: '/components/BMetricTip'},
97+
{ text: 'BCharts', link: '/components/BCharts'}
9798
]
9899
},
99100
{
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<template>
2+
<div class="wd-content-body">
3+
<h4 class="chart-title">{{ config.title }}</h4>
4+
<div class="date-range">
5+
<div class="mr16 my-date-picker">
6+
<FDatePicker type="daterange" v-model="dateRange" @change="updateDateRange" />
7+
</div>
8+
<FButton key="btn-1" class="mr16" :class="{ 'my-btn': true, active: days === 7 }" @click="updateDays(7)">
9+
最近7天
10+
</FButton>
11+
<FButton key="btn-2" :class="{ 'my-btn': true, active: days === 30 }" @click="updateDays(30)">
12+
最近30天
13+
</FButton>
14+
</div>
15+
<div :id="chartId" class="chart-container">
16+
</div>
17+
</div>
18+
</template>
19+
20+
<script setup lang="ts">
21+
import { ref, computed } from 'vue';
22+
import { FDatePicker, FButton } from '@fesjs/fes-design';
23+
import { useChart, type ChartConfig } from './useChart';
24+
import {
25+
getYear, getMonth, getDate, subDays, differenceInDays,
26+
} from 'date-fns';
27+
28+
29+
30+
interface Props {
31+
chartId: string;
32+
config: ChartConfig;
33+
initialDays?: number;
34+
}
35+
36+
const props = defineProps<Props>();
37+
38+
// 日期范围相关
39+
const days = ref(props.initialDays || 7);
40+
const initialEndDate = new Date().getTime();
41+
const initialStartDate = subDays(new Date(initialEndDate), days.value - 1).getTime();
42+
const endDate = ref(initialEndDate);
43+
const startDate = ref(initialStartDate);
44+
45+
// 初始化时,开始日期在前,结束日期在后
46+
const dateRange = ref([initialStartDate, initialEndDate]);
47+
48+
const updateDateRange = (range: number[]) => {
49+
const [startStamp, endStamp] = range;
50+
startDate.value = startStamp;
51+
endDate.value = endStamp;
52+
const now = Date.now();
53+
if (startStamp && endStamp) {
54+
const isToday = getYear(now) === getYear(endStamp)
55+
&& getMonth(now) === getMonth(endStamp)
56+
&& getDate(now) === getDate(endStamp);
57+
const daysDiff = differenceInDays(endStamp, startStamp) + 1;
58+
if (isToday && [7, 30].includes(daysDiff)) {
59+
days.value = daysDiff;
60+
} else {
61+
days.value = 0;
62+
}
63+
}
64+
};
65+
66+
const updateDays = (newDays: number) => {
67+
const _endDate = new Date();
68+
const _startDate = subDays(_endDate, newDays - 1);
69+
dateRange.value = [_startDate.getTime(), _endDate.getTime()];
70+
days.value = newDays;
71+
startDate.value = _startDate.getTime();
72+
endDate.value = _endDate.getTime();
73+
};
74+
75+
// 图表相关
76+
const { loading } = useChart(
77+
props.chartId,
78+
props.config,
79+
startDate,
80+
endDate
81+
);
82+
</script>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { withInstall } from '../_util/withInstall';
2+
import Charts from './Charts.vue';
3+
4+
import type { SFCWithInstall } from '../_util/interface';
5+
6+
type ChartsType = SFCWithInstall<typeof Charts>;
7+
export const BCharts = withInstall<ChartsType>(Charts as ChartsType);
8+
9+
export default BCharts;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
.wd-content-body {
2+
width: 100%;
3+
}
4+
5+
.chart-title {
6+
margin-bottom: 16px;
7+
}
8+
9+
.date-range {
10+
display: flex;
11+
align-items: center;
12+
margin-bottom: 16px;
13+
}
14+
15+
.chart-container {
16+
position: relative;
17+
width: 100%;
18+
height: 400px;
19+
}
20+
21+
.loading-overlay {
22+
position: absolute;
23+
top: 0;
24+
left: 0;
25+
right: 0;
26+
bottom: 0;
27+
display: flex;
28+
align-items: center;
29+
justify-content: center;
30+
background: rgba(255, 255, 255, 0.7);
31+
}
32+
33+
.mr16 {
34+
margin-right: 16px;
35+
}
36+
37+
.my-btn.active {
38+
background-color: #f5f8ff;
39+
border-color: #5384ff;
40+
color: #5384ff;
41+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './index.less';

0 commit comments

Comments
 (0)