@vela-studio/ui 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -0
- package/dist/index.d.ts +696 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +11786 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.umd.js +10 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/style.css +1 -0
- package/index.ts +150 -0
- package/package.json +73 -0
- package/src/components/advanced/scripting/Scripting.vue +189 -0
- package/src/components/advanced/state/State.vue +231 -0
- package/src/components/advanced/trigger/Trigger.vue +256 -0
- package/src/components/basic/button/Button.vue +120 -0
- package/src/components/basic/container/Container.vue +22 -0
- package/src/components/chart/barChart/barChart.vue +176 -0
- package/src/components/chart/doughnutChart/doughnutChart.vue +128 -0
- package/src/components/chart/funnelChart/funnelChart.vue +128 -0
- package/src/components/chart/gaugeChart/gaugeChart.vue +144 -0
- package/src/components/chart/lineChart/lineChart.vue +188 -0
- package/src/components/chart/pieChart/pieChart.vue +114 -0
- package/src/components/chart/radarChart/radarChart.vue +115 -0
- package/src/components/chart/sankeyChart/sankeyChart.vue +144 -0
- package/src/components/chart/scatterChart/scatterChart.vue +162 -0
- package/src/components/chart/stackedBarChart/stackedBarChart.vue +184 -0
- package/src/components/content/html/Html.vue +104 -0
- package/src/components/content/iframe/Iframe.vue +111 -0
- package/src/components/content/markdown/Markdown.vue +174 -0
- package/src/components/controls/breadcrumb/Breadcrumb.vue +79 -0
- package/src/components/controls/buttonGroup/ButtonGroup.vue +93 -0
- package/src/components/controls/checkboxGroup/CheckboxGroup.vue +147 -0
- package/src/components/controls/dateRange/DateRange.vue +174 -0
- package/src/components/controls/multiSelect/MultiSelect.vue +155 -0
- package/src/components/controls/navButton/NavButton.vue +97 -0
- package/src/components/controls/pagination/Pagination.vue +94 -0
- package/src/components/controls/searchBox/SearchBox.vue +170 -0
- package/src/components/controls/select/Select.vue +134 -0
- package/src/components/controls/slider/Slider.vue +167 -0
- package/src/components/controls/switch/Switch.vue +107 -0
- package/src/components/data/cardGrid/CardGrid.vue +318 -0
- package/src/components/data/list/List.vue +282 -0
- package/src/components/data/pivot/Pivot.vue +270 -0
- package/src/components/data/table/Table.vue +150 -0
- package/src/components/data/timeline/Timeline.vue +315 -0
- package/src/components/group/Group.vue +75 -0
- package/src/components/kpi/box/Box.vue +98 -0
- package/src/components/kpi/countUp/CountUp.vue +193 -0
- package/src/components/kpi/progress/Progress.vue +159 -0
- package/src/components/kpi/stat/Stat.vue +205 -0
- package/src/components/kpi/text/Text.vue +74 -0
- package/src/components/layout/badge/Badge.vue +105 -0
- package/src/components/layout/col/Col.vue +114 -0
- package/src/components/layout/flex/Flex.vue +105 -0
- package/src/components/layout/grid/Grid.vue +89 -0
- package/src/components/layout/modal/Modal.vue +118 -0
- package/src/components/layout/panel/Panel.vue +162 -0
- package/src/components/layout/row/Row.vue +99 -0
- package/src/components/layout/tabs/Tabs.vue +117 -0
- package/src/components/media/image/Image.vue +132 -0
- package/src/components/media/video/Video.vue +115 -0
- package/src/components/v2/basic/BaseButton.vue +179 -0
- package/src/components/v2/kpi/KpiCard.vue +215 -0
- package/src/components/v2/layout/GridBox.vue +55 -0
- package/src/hooks/useDataSource.ts +123 -0
- package/src/types/gis.ts +251 -0
- package/src/utils/chartUtils.ts +349 -0
- package/src/utils/dataUtils.ts +403 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="v-funnel-chart" :style="{ width: '100%', height: '100%' }">
|
|
3
|
+
<v-chart :option="finalOption" autoresize class="echart" />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import { computed } from 'vue'
|
|
9
|
+
import { use } from 'echarts/core'
|
|
10
|
+
import { CanvasRenderer } from 'echarts/renderers'
|
|
11
|
+
import { FunnelChart } from 'echarts/charts'
|
|
12
|
+
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
|
|
13
|
+
import VChart from 'vue-echarts'
|
|
14
|
+
import type { EChartsOption } from 'echarts'
|
|
15
|
+
|
|
16
|
+
// 注册 ECharts 组件
|
|
17
|
+
use([TitleComponent, TooltipComponent, LegendComponent, FunnelChart, CanvasRenderer])
|
|
18
|
+
|
|
19
|
+
// 定义标准的 Props,不含任何业务逻辑 ID
|
|
20
|
+
const props = defineProps<{
|
|
21
|
+
// 基础数据 Props
|
|
22
|
+
data?: Array<{ name: string; value: number }>
|
|
23
|
+
|
|
24
|
+
// 样式配置 Props
|
|
25
|
+
title?: string
|
|
26
|
+
seriesName?: string
|
|
27
|
+
left?: string
|
|
28
|
+
top?: string
|
|
29
|
+
bottom?: string
|
|
30
|
+
width?: string
|
|
31
|
+
min?: number
|
|
32
|
+
max?: number
|
|
33
|
+
minSize?: string
|
|
34
|
+
maxSize?: string
|
|
35
|
+
sort?: 'descending' | 'ascending' | 'none'
|
|
36
|
+
gap?: number
|
|
37
|
+
showLabel?: boolean
|
|
38
|
+
labelPosition?: 'left' | 'right' | 'inside'
|
|
39
|
+
labelFormatter?: string
|
|
40
|
+
showLabelLine?: boolean
|
|
41
|
+
labelLineLength?: number
|
|
42
|
+
borderColor?: string
|
|
43
|
+
borderWidth?: number
|
|
44
|
+
|
|
45
|
+
// 高级覆盖
|
|
46
|
+
option?: EChartsOption
|
|
47
|
+
}>()
|
|
48
|
+
|
|
49
|
+
// 默认值配置
|
|
50
|
+
const defaultData = [
|
|
51
|
+
{ name: '展示', value: 100 },
|
|
52
|
+
{ name: '访问', value: 80 },
|
|
53
|
+
{ name: '咨询', value: 60 },
|
|
54
|
+
{ name: '订单', value: 40 },
|
|
55
|
+
{ name: '成交', value: 20 },
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
// 计算最终 Option
|
|
59
|
+
const finalOption = computed<EChartsOption>(() => {
|
|
60
|
+
// 如果有高级配置 option,优先使用
|
|
61
|
+
if (props.option && Object.keys(props.option).length > 0) return props.option
|
|
62
|
+
|
|
63
|
+
const data = props.data && props.data.length ? props.data : defaultData
|
|
64
|
+
const seriesName = props.seriesName || 'Funnel'
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
title: {
|
|
68
|
+
text: props.title || '',
|
|
69
|
+
left: 'center',
|
|
70
|
+
},
|
|
71
|
+
tooltip: {
|
|
72
|
+
trigger: 'item',
|
|
73
|
+
formatter: '{b}: {c}',
|
|
74
|
+
},
|
|
75
|
+
legend: {
|
|
76
|
+
bottom: 10,
|
|
77
|
+
data: data.map((d) => d.name),
|
|
78
|
+
},
|
|
79
|
+
series: [
|
|
80
|
+
{
|
|
81
|
+
name: seriesName,
|
|
82
|
+
type: 'funnel',
|
|
83
|
+
left: props.left || '10%',
|
|
84
|
+
top: props.top || '20%',
|
|
85
|
+
bottom: props.bottom || '20%',
|
|
86
|
+
width: props.width || '80%',
|
|
87
|
+
min: props.min || 0,
|
|
88
|
+
max: props.max || 100,
|
|
89
|
+
minSize: props.minSize || '0%',
|
|
90
|
+
maxSize: props.maxSize || '100%',
|
|
91
|
+
sort: props.sort || 'descending',
|
|
92
|
+
gap: props.gap || 2,
|
|
93
|
+
label: {
|
|
94
|
+
show: props.showLabel !== false,
|
|
95
|
+
position: props.labelPosition || 'inside',
|
|
96
|
+
formatter: props.labelFormatter || '{b}: {c}',
|
|
97
|
+
},
|
|
98
|
+
labelLine: {
|
|
99
|
+
show: props.showLabelLine !== false,
|
|
100
|
+
length: props.labelLineLength || 10,
|
|
101
|
+
},
|
|
102
|
+
itemStyle: {
|
|
103
|
+
borderColor: props.borderColor || '#fff',
|
|
104
|
+
borderWidth: props.borderWidth || 1,
|
|
105
|
+
},
|
|
106
|
+
emphasis: {
|
|
107
|
+
label: {
|
|
108
|
+
fontSize: 20,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
data: data,
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
</script>
|
|
117
|
+
|
|
118
|
+
<style scoped>
|
|
119
|
+
.v-funnel-chart {
|
|
120
|
+
width: 100%;
|
|
121
|
+
height: 100%;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.echart {
|
|
125
|
+
width: 100%;
|
|
126
|
+
height: 100%;
|
|
127
|
+
}
|
|
128
|
+
</style>
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="v-gauge-chart" :style="{ width: '100%', height: '100%' }">
|
|
3
|
+
<v-chart :option="finalOption" autoresize class="echart" />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import { computed } from 'vue'
|
|
9
|
+
import { use } from 'echarts/core'
|
|
10
|
+
import { CanvasRenderer } from 'echarts/renderers'
|
|
11
|
+
import { GaugeChart } from 'echarts/charts'
|
|
12
|
+
import { TitleComponent, TooltipComponent } from 'echarts/components'
|
|
13
|
+
import VChart from 'vue-echarts'
|
|
14
|
+
import type { EChartsOption } from 'echarts'
|
|
15
|
+
|
|
16
|
+
// 注册 ECharts 组件
|
|
17
|
+
use([TitleComponent, TooltipComponent, GaugeChart, CanvasRenderer])
|
|
18
|
+
|
|
19
|
+
// 定义标准的 Props,不含任何业务逻辑 ID
|
|
20
|
+
const props = defineProps<{
|
|
21
|
+
// 基础数据 Props
|
|
22
|
+
value?: number
|
|
23
|
+
name?: string
|
|
24
|
+
min?: number
|
|
25
|
+
max?: number
|
|
26
|
+
|
|
27
|
+
// 样式配置 Props
|
|
28
|
+
title?: string
|
|
29
|
+
startAngle?: number
|
|
30
|
+
endAngle?: number
|
|
31
|
+
splitNumber?: number
|
|
32
|
+
showProgress?: boolean
|
|
33
|
+
progressWidth?: number
|
|
34
|
+
axisLineWidth?: number
|
|
35
|
+
axisLineColor?: Array<[number, string]>
|
|
36
|
+
pointerColor?: string
|
|
37
|
+
pointerLength?: string
|
|
38
|
+
pointerWidth?: number
|
|
39
|
+
showAxisTick?: boolean
|
|
40
|
+
axisTickSplitNumber?: number
|
|
41
|
+
showSplitLine?: boolean
|
|
42
|
+
splitLineLength?: number
|
|
43
|
+
showAxisLabel?: boolean
|
|
44
|
+
axisLabelDistance?: number
|
|
45
|
+
axisLabelFontSize?: number
|
|
46
|
+
detailFormatter?: string
|
|
47
|
+
detailFontSize?: number
|
|
48
|
+
detailOffsetX?: string
|
|
49
|
+
detailOffsetY?: string
|
|
50
|
+
|
|
51
|
+
// 高级覆盖
|
|
52
|
+
option?: EChartsOption
|
|
53
|
+
}>()
|
|
54
|
+
|
|
55
|
+
// 计算最终 Option
|
|
56
|
+
const finalOption = computed<EChartsOption>(() => {
|
|
57
|
+
// 如果有高级配置 option,优先使用
|
|
58
|
+
if (props.option && Object.keys(props.option).length > 0) return props.option
|
|
59
|
+
|
|
60
|
+
const value = props.value ?? 75
|
|
61
|
+
const name = props.name || 'Progress'
|
|
62
|
+
const min = props.min ?? 0
|
|
63
|
+
const max = props.max ?? 100
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
title: {
|
|
67
|
+
text: props.title || '',
|
|
68
|
+
left: 'center',
|
|
69
|
+
},
|
|
70
|
+
tooltip: {
|
|
71
|
+
formatter: '{b}: {c}',
|
|
72
|
+
},
|
|
73
|
+
series: [
|
|
74
|
+
{
|
|
75
|
+
name: name,
|
|
76
|
+
type: 'gauge',
|
|
77
|
+
min: min,
|
|
78
|
+
max: max,
|
|
79
|
+
startAngle: props.startAngle || 225,
|
|
80
|
+
endAngle: props.endAngle || -45,
|
|
81
|
+
splitNumber: props.splitNumber || 10,
|
|
82
|
+
progress: {
|
|
83
|
+
show: props.showProgress !== false,
|
|
84
|
+
width: props.progressWidth || 10,
|
|
85
|
+
},
|
|
86
|
+
axisLine: {
|
|
87
|
+
lineStyle: {
|
|
88
|
+
width: props.axisLineWidth || 10,
|
|
89
|
+
color: props.axisLineColor || [
|
|
90
|
+
[0.3, '#67e0e3'],
|
|
91
|
+
[0.7, '#37a2da'],
|
|
92
|
+
[1, '#fd666d'],
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
pointer: {
|
|
97
|
+
itemStyle: {
|
|
98
|
+
color: props.pointerColor || 'auto',
|
|
99
|
+
},
|
|
100
|
+
length: props.pointerLength || '70%',
|
|
101
|
+
width: props.pointerWidth || 8,
|
|
102
|
+
},
|
|
103
|
+
axisTick: {
|
|
104
|
+
show: props.showAxisTick !== false,
|
|
105
|
+
splitNumber: props.axisTickSplitNumber || 5,
|
|
106
|
+
},
|
|
107
|
+
splitLine: {
|
|
108
|
+
show: props.showSplitLine !== false,
|
|
109
|
+
length: props.splitLineLength || 15,
|
|
110
|
+
},
|
|
111
|
+
axisLabel: {
|
|
112
|
+
show: props.showAxisLabel !== false,
|
|
113
|
+
distance: props.axisLabelDistance || 25,
|
|
114
|
+
fontSize: props.axisLabelFontSize || 12,
|
|
115
|
+
},
|
|
116
|
+
detail: {
|
|
117
|
+
valueAnimation: true,
|
|
118
|
+
formatter: props.detailFormatter || '{value}',
|
|
119
|
+
fontSize: props.detailFontSize || 20,
|
|
120
|
+
offsetCenter: [props.detailOffsetX || '0%', props.detailOffsetY || '70%'],
|
|
121
|
+
},
|
|
122
|
+
data: [
|
|
123
|
+
{
|
|
124
|
+
value: value,
|
|
125
|
+
name: name,
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
</script>
|
|
133
|
+
|
|
134
|
+
<style scoped>
|
|
135
|
+
.v-gauge-chart {
|
|
136
|
+
width: 100%;
|
|
137
|
+
height: 100%;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.echart {
|
|
141
|
+
width: 100%;
|
|
142
|
+
height: 100%;
|
|
143
|
+
}
|
|
144
|
+
</style>
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="v-line-chart" :style="{ width: '100%', height: '100%' }">
|
|
3
|
+
<v-chart :option="finalOption" autoresize class="echart" />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import { computed } from 'vue'
|
|
9
|
+
import { use } from 'echarts/core'
|
|
10
|
+
import { CanvasRenderer } from 'echarts/renderers'
|
|
11
|
+
import { LineChart } from 'echarts/charts'
|
|
12
|
+
import {
|
|
13
|
+
TitleComponent,
|
|
14
|
+
TooltipComponent,
|
|
15
|
+
GridComponent,
|
|
16
|
+
LegendComponent,
|
|
17
|
+
} from 'echarts/components'
|
|
18
|
+
import VChart from 'vue-echarts'
|
|
19
|
+
import type { EChartsOption } from 'echarts'
|
|
20
|
+
|
|
21
|
+
// 注册 ECharts 组件
|
|
22
|
+
use([TitleComponent, TooltipComponent, GridComponent, LegendComponent, LineChart, CanvasRenderer])
|
|
23
|
+
|
|
24
|
+
// 定义标准的 Props,不含任何业务逻辑 ID
|
|
25
|
+
const props = defineProps<{
|
|
26
|
+
// 基础数据 Props
|
|
27
|
+
data?: number[]
|
|
28
|
+
xAxisData?: string[]
|
|
29
|
+
seriesName?: string
|
|
30
|
+
|
|
31
|
+
// 样式配置 Props
|
|
32
|
+
title?: string
|
|
33
|
+
lineColor?: string
|
|
34
|
+
smooth?: boolean
|
|
35
|
+
showArea?: boolean
|
|
36
|
+
showTooltip?: boolean
|
|
37
|
+
showLegend?: boolean
|
|
38
|
+
legendPosition?: 'top' | 'bottom' | 'left' | 'right'
|
|
39
|
+
showGrid?: boolean
|
|
40
|
+
xAxisName?: string
|
|
41
|
+
yAxisName?: string
|
|
42
|
+
showXAxisLine?: boolean
|
|
43
|
+
showXAxisLabel?: boolean
|
|
44
|
+
showYAxisLine?: boolean
|
|
45
|
+
showYAxisLabel?: boolean
|
|
46
|
+
symbolSize?: number
|
|
47
|
+
lineWidth?: number
|
|
48
|
+
lineType?: 'solid' | 'dashed' | 'dotted'
|
|
49
|
+
areaOpacity?: number
|
|
50
|
+
showSymbol?: boolean
|
|
51
|
+
|
|
52
|
+
// 高级覆盖
|
|
53
|
+
option?: EChartsOption
|
|
54
|
+
}>()
|
|
55
|
+
|
|
56
|
+
// 默认值配置
|
|
57
|
+
const defaultData = [150, 230, 224, 218, 135, 147, 260]
|
|
58
|
+
const defaultXAxis = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
|
59
|
+
|
|
60
|
+
// 计算最终 Option
|
|
61
|
+
const finalOption = computed<EChartsOption>(() => {
|
|
62
|
+
// 如果有高级配置 option,优先使用
|
|
63
|
+
if (props.option && Object.keys(props.option).length > 0) return props.option
|
|
64
|
+
|
|
65
|
+
const data = props.data && props.data.length ? props.data : defaultData
|
|
66
|
+
const xAxisData = props.xAxisData && props.xAxisData.length ? props.xAxisData : defaultXAxis
|
|
67
|
+
const seriesName = props.seriesName || 'Series'
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
// 标题
|
|
71
|
+
title: props.title
|
|
72
|
+
? {
|
|
73
|
+
text: props.title,
|
|
74
|
+
left: 'center',
|
|
75
|
+
textStyle: {
|
|
76
|
+
fontSize: 16,
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
: undefined,
|
|
80
|
+
|
|
81
|
+
// 提示框
|
|
82
|
+
tooltip:
|
|
83
|
+
props.showTooltip !== false
|
|
84
|
+
? {
|
|
85
|
+
trigger: 'axis',
|
|
86
|
+
axisPointer: {
|
|
87
|
+
type: 'cross',
|
|
88
|
+
label: {
|
|
89
|
+
backgroundColor: '#6a7985',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
: undefined,
|
|
94
|
+
|
|
95
|
+
// 图例
|
|
96
|
+
legend:
|
|
97
|
+
props.showLegend !== false
|
|
98
|
+
? {
|
|
99
|
+
[(props.legendPosition as string) || 'top']: 10,
|
|
100
|
+
data: [seriesName],
|
|
101
|
+
}
|
|
102
|
+
: undefined,
|
|
103
|
+
|
|
104
|
+
// 网格
|
|
105
|
+
grid: {
|
|
106
|
+
left: '6%',
|
|
107
|
+
right: '6%',
|
|
108
|
+
bottom: '8%',
|
|
109
|
+
top: props.title ? '15%' : '10%',
|
|
110
|
+
containLabel: true,
|
|
111
|
+
show: props.showGrid !== false,
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
// X 轴
|
|
115
|
+
xAxis: {
|
|
116
|
+
type: 'category',
|
|
117
|
+
data: xAxisData,
|
|
118
|
+
name: props.xAxisName || '',
|
|
119
|
+
nameLocation: 'middle',
|
|
120
|
+
nameGap: 30,
|
|
121
|
+
axisLine: {
|
|
122
|
+
show: props.showXAxisLine !== false,
|
|
123
|
+
},
|
|
124
|
+
axisLabel: {
|
|
125
|
+
show: props.showXAxisLabel !== false,
|
|
126
|
+
},
|
|
127
|
+
splitLine: {
|
|
128
|
+
show: props.showGrid !== false,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
// Y 轴
|
|
133
|
+
yAxis: {
|
|
134
|
+
type: 'value',
|
|
135
|
+
name: props.yAxisName || '',
|
|
136
|
+
nameLocation: 'middle',
|
|
137
|
+
nameGap: 50,
|
|
138
|
+
axisLine: {
|
|
139
|
+
show: props.showYAxisLine !== false,
|
|
140
|
+
},
|
|
141
|
+
axisLabel: {
|
|
142
|
+
show: props.showYAxisLabel !== false,
|
|
143
|
+
},
|
|
144
|
+
splitLine: {
|
|
145
|
+
show: props.showGrid !== false,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
// 系列
|
|
150
|
+
series: [
|
|
151
|
+
{
|
|
152
|
+
name: seriesName,
|
|
153
|
+
type: 'line',
|
|
154
|
+
data: data,
|
|
155
|
+
smooth: props.smooth !== false,
|
|
156
|
+
showSymbol: props.showSymbol !== false,
|
|
157
|
+
symbolSize: props.symbolSize || 6,
|
|
158
|
+
lineStyle: {
|
|
159
|
+
color: props.lineColor || '#5470c6',
|
|
160
|
+
width: props.lineWidth || 2,
|
|
161
|
+
type: props.lineType || 'solid',
|
|
162
|
+
},
|
|
163
|
+
itemStyle: {
|
|
164
|
+
color: props.lineColor || '#5470c6',
|
|
165
|
+
},
|
|
166
|
+
areaStyle: props.showArea
|
|
167
|
+
? {
|
|
168
|
+
color: props.lineColor || '#5470c6',
|
|
169
|
+
opacity: props.areaOpacity || 0.3,
|
|
170
|
+
}
|
|
171
|
+
: undefined,
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
</script>
|
|
177
|
+
|
|
178
|
+
<style scoped>
|
|
179
|
+
.v-line-chart {
|
|
180
|
+
width: 100%;
|
|
181
|
+
height: 100%;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.echart {
|
|
185
|
+
width: 100%;
|
|
186
|
+
height: 100%;
|
|
187
|
+
}
|
|
188
|
+
</style>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="v-pie-chart" :style="{ width: '100%', height: '100%' }">
|
|
3
|
+
<v-chart :option="finalOption" autoresize class="echart" />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import { computed } from 'vue'
|
|
9
|
+
import { use } from 'echarts/core'
|
|
10
|
+
import { CanvasRenderer } from 'echarts/renderers'
|
|
11
|
+
import { PieChart } from 'echarts/charts'
|
|
12
|
+
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
|
|
13
|
+
import VChart from 'vue-echarts'
|
|
14
|
+
import type { EChartsOption } from 'echarts'
|
|
15
|
+
|
|
16
|
+
// 注册 ECharts 组件
|
|
17
|
+
use([TitleComponent, TooltipComponent, LegendComponent, PieChart, CanvasRenderer])
|
|
18
|
+
|
|
19
|
+
// 定义标准的 Props,不含任何业务逻辑 ID
|
|
20
|
+
const props = defineProps<{
|
|
21
|
+
// 基础数据 Props
|
|
22
|
+
data?: Array<{ name: string; value: number }>
|
|
23
|
+
|
|
24
|
+
// 样式配置 Props
|
|
25
|
+
title?: string
|
|
26
|
+
titleAlign?: 'left' | 'center' | 'right'
|
|
27
|
+
titleSize?: number
|
|
28
|
+
titleColor?: string
|
|
29
|
+
seriesName?: string
|
|
30
|
+
radius?: string
|
|
31
|
+
centerX?: string
|
|
32
|
+
centerY?: string
|
|
33
|
+
showLegend?: boolean
|
|
34
|
+
legendOrient?: 'horizontal' | 'vertical'
|
|
35
|
+
legendLeft?: string
|
|
36
|
+
legendTop?: string
|
|
37
|
+
showLabel?: boolean
|
|
38
|
+
labelFormatter?: string
|
|
39
|
+
|
|
40
|
+
// 高级覆盖
|
|
41
|
+
option?: EChartsOption
|
|
42
|
+
}>()
|
|
43
|
+
|
|
44
|
+
// 默认值配置
|
|
45
|
+
const defaultData = [
|
|
46
|
+
{ name: 'Category A', value: 335 },
|
|
47
|
+
{ name: 'Category B', value: 310 },
|
|
48
|
+
{ name: 'Category C', value: 234 },
|
|
49
|
+
{ name: 'Category D', value: 135 },
|
|
50
|
+
{ name: 'Category E', value: 148 },
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
// 计算最终 Option
|
|
54
|
+
const finalOption = computed<EChartsOption>(() => {
|
|
55
|
+
// 如果有高级配置 option,优先使用
|
|
56
|
+
if (props.option && Object.keys(props.option).length > 0) return props.option
|
|
57
|
+
|
|
58
|
+
const data = props.data && props.data.length ? props.data : defaultData
|
|
59
|
+
const seriesName = props.seriesName || 'Data'
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
title: {
|
|
63
|
+
text: props.title || '',
|
|
64
|
+
left: props.titleAlign || 'center',
|
|
65
|
+
textStyle: {
|
|
66
|
+
fontSize: props.titleSize || 16,
|
|
67
|
+
color: props.titleColor || '#333',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
tooltip: {
|
|
71
|
+
trigger: 'item',
|
|
72
|
+
formatter: '{a} <br/>{b}: {c} ({d}%)',
|
|
73
|
+
},
|
|
74
|
+
legend: {
|
|
75
|
+
show: props.showLegend !== false,
|
|
76
|
+
orient: props.legendOrient || 'horizontal',
|
|
77
|
+
left: props.legendLeft || 'center',
|
|
78
|
+
top: props.legendTop || 'bottom',
|
|
79
|
+
},
|
|
80
|
+
series: [
|
|
81
|
+
{
|
|
82
|
+
name: seriesName,
|
|
83
|
+
type: 'pie',
|
|
84
|
+
radius: props.radius || '60%',
|
|
85
|
+
center: [props.centerX || '50%', props.centerY || '50%'],
|
|
86
|
+
data: data,
|
|
87
|
+
label: {
|
|
88
|
+
show: props.showLabel !== false,
|
|
89
|
+
formatter: props.labelFormatter || '{b}: {c}',
|
|
90
|
+
},
|
|
91
|
+
emphasis: {
|
|
92
|
+
itemStyle: {
|
|
93
|
+
shadowBlur: 10,
|
|
94
|
+
shadowOffsetX: 0,
|
|
95
|
+
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<style scoped>
|
|
105
|
+
.v-pie-chart {
|
|
106
|
+
width: 100%;
|
|
107
|
+
height: 100%;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.echart {
|
|
111
|
+
width: 100%;
|
|
112
|
+
height: 100%;
|
|
113
|
+
}
|
|
114
|
+
</style>
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="v-radar-chart" :style="{ width: '100%', height: '100%' }">
|
|
3
|
+
<v-chart :option="finalOption" autoresize class="echart" />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import { computed } from 'vue'
|
|
9
|
+
import { use } from 'echarts/core'
|
|
10
|
+
import { CanvasRenderer } from 'echarts/renderers'
|
|
11
|
+
import { RadarChart } from 'echarts/charts'
|
|
12
|
+
import {
|
|
13
|
+
TitleComponent,
|
|
14
|
+
TooltipComponent,
|
|
15
|
+
LegendComponent,
|
|
16
|
+
RadarComponent,
|
|
17
|
+
} from 'echarts/components'
|
|
18
|
+
import VChart from 'vue-echarts'
|
|
19
|
+
import type { EChartsOption } from 'echarts'
|
|
20
|
+
|
|
21
|
+
// 注册 ECharts 组件
|
|
22
|
+
use([TitleComponent, TooltipComponent, LegendComponent, RadarComponent, RadarChart, CanvasRenderer])
|
|
23
|
+
|
|
24
|
+
// 定义标准的 Props,不含任何业务逻辑 ID
|
|
25
|
+
const props = defineProps<{
|
|
26
|
+
// 基础数据 Props
|
|
27
|
+
indicators?: Array<{ name: string; max: number }>
|
|
28
|
+
seriesData?: Array<{ name: string; value: number[] }>
|
|
29
|
+
|
|
30
|
+
// 样式配置 Props
|
|
31
|
+
title?: string
|
|
32
|
+
seriesName?: string
|
|
33
|
+
radarShape?: 'polygon' | 'circle'
|
|
34
|
+
splitNumber?: number
|
|
35
|
+
axisNameColor?: string
|
|
36
|
+
showArea?: boolean
|
|
37
|
+
areaOpacity?: number
|
|
38
|
+
|
|
39
|
+
// 高级覆盖
|
|
40
|
+
option?: EChartsOption
|
|
41
|
+
}>()
|
|
42
|
+
|
|
43
|
+
// 默认值配置
|
|
44
|
+
const defaultIndicators = [
|
|
45
|
+
{ name: '销售', max: 100 },
|
|
46
|
+
{ name: '管理', max: 100 },
|
|
47
|
+
{ name: '技术', max: 100 },
|
|
48
|
+
{ name: '客服', max: 100 },
|
|
49
|
+
{ name: '研发', max: 100 },
|
|
50
|
+
{ name: '市场', max: 100 },
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
const defaultSeriesData = [
|
|
54
|
+
{ name: '预算', value: [43, 85, 70, 75, 68, 92] },
|
|
55
|
+
{ name: '实际开销', value: [50, 90, 60, 82, 73, 85] },
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
// 计算最终 Option
|
|
59
|
+
const finalOption = computed<EChartsOption>(() => {
|
|
60
|
+
// 如果有高级配置 option,优先使用
|
|
61
|
+
if (props.option && Object.keys(props.option).length > 0) return props.option
|
|
62
|
+
|
|
63
|
+
const indicators =
|
|
64
|
+
props.indicators && props.indicators.length ? props.indicators : defaultIndicators
|
|
65
|
+
const seriesData =
|
|
66
|
+
props.seriesData && props.seriesData.length ? props.seriesData : defaultSeriesData
|
|
67
|
+
const seriesName = props.seriesName || 'Radar'
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
title: {
|
|
71
|
+
text: props.title || '',
|
|
72
|
+
left: 'center',
|
|
73
|
+
},
|
|
74
|
+
tooltip: {
|
|
75
|
+
trigger: 'item',
|
|
76
|
+
},
|
|
77
|
+
legend: {
|
|
78
|
+
bottom: 10,
|
|
79
|
+
data: seriesData.map((s) => s.name),
|
|
80
|
+
},
|
|
81
|
+
radar: {
|
|
82
|
+
indicator: indicators,
|
|
83
|
+
shape: props.radarShape || 'polygon',
|
|
84
|
+
splitNumber: props.splitNumber || 5,
|
|
85
|
+
axisName: {
|
|
86
|
+
color: props.axisNameColor || '#333',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
series: [
|
|
90
|
+
{
|
|
91
|
+
name: seriesName,
|
|
92
|
+
type: 'radar',
|
|
93
|
+
data: seriesData,
|
|
94
|
+
areaStyle: props.showArea
|
|
95
|
+
? {
|
|
96
|
+
opacity: props.areaOpacity || 0.3,
|
|
97
|
+
}
|
|
98
|
+
: undefined,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
</script>
|
|
104
|
+
|
|
105
|
+
<style scoped>
|
|
106
|
+
.v-radar-chart {
|
|
107
|
+
width: 100%;
|
|
108
|
+
height: 100%;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.echart {
|
|
112
|
+
width: 100%;
|
|
113
|
+
height: 100%;
|
|
114
|
+
}
|
|
115
|
+
</style>
|