1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
| <!-- k线图表 -->
| <template>
| <div
| ref="chartRef"
| class="relative w-full"
| :style="{ height: props.height }"
| v-loading="props.loading"
| ></div>
| </template>
|
| <script setup>
| import { useChartOps, useChartComponent } from '@/hooks/core/useChart'
| defineOptions({ name: 'ArtKLineChart' })
| const props = defineProps({
| height: { required: false, default: useChartOps().chartHeight },
| loading: { required: false, default: false },
| isEmpty: { required: false, default: false },
| colors: { required: false, default: () => useChartOps().colors },
| data: { required: false, default: () => [] },
| showDataZoom: { required: false, default: false },
| dataZoomStart: { required: false, default: 0 },
| dataZoomEnd: { required: false, default: 100 }
| })
| const getActualColors = () => {
| const defaultUpColor = '#4C87F3'
| const defaultDownColor = '#8BD8FC'
| return {
| upColor: props.colors?.[0] || defaultUpColor,
| downColor: props.colors?.[1] || defaultDownColor
| }
| }
| const {
| chartRef,
| getAxisLineStyle,
| getAxisLabelStyle,
| getAxisTickStyle,
| getSplitLineStyle,
| getAnimationConfig,
| getTooltipStyle
| } = useChartComponent({
| props,
| checkEmpty: () => {
| return (
| !props.data?.length ||
| props.data.every(
| (item) => item.open === 0 && item.close === 0 && item.high === 0 && item.low === 0
| )
| )
| },
| watchSources: [
| () => props.data,
| () => props.colors,
| () => props.showDataZoom,
| () => props.dataZoomStart,
| () => props.dataZoomEnd
| ],
| generateOptions: () => {
| const { upColor, downColor } = getActualColors()
| return {
| grid: {
| top: 20,
| right: 20,
| bottom: props.showDataZoom ? 80 : 20,
| left: 20,
| containLabel: true
| },
| tooltip: getTooltipStyle('axis', {
| axisPointer: {
| type: 'cross'
| },
| formatter: (params) => {
| const param = params[0]
| const data = param.data
| return `
| <div style="padding: 5px;">
| <div><strong>时间:</strong>${param.name}</div>
| <div><strong>开盘:</strong>${data[0]}</div>
| <div><strong>收盘:</strong>${data[1]}</div>
| <div><strong>最低:</strong>${data[2]}</div>
| <div><strong>最高:</strong>${data[3]}</div>
| </div>
| `
| }
| }),
| xAxis: {
| type: 'category',
| data: props.data.map((item) => item.time),
| axisTick: getAxisTickStyle(),
| axisLine: getAxisLineStyle(true),
| axisLabel: getAxisLabelStyle(true)
| },
| yAxis: {
| type: 'value',
| scale: true,
| axisLabel: getAxisLabelStyle(true),
| axisLine: getAxisLineStyle(true),
| splitLine: getSplitLineStyle(true)
| },
| series: [
| {
| type: 'candlestick',
| data: props.data.map((item) => [item.open, item.close, item.low, item.high]),
| itemStyle: {
| color: upColor,
| color0: downColor,
| borderColor: upColor,
| borderColor0: downColor,
| borderWidth: 1
| },
| emphasis: {
| itemStyle: {
| borderWidth: 2,
| shadowBlur: 10,
| shadowColor: 'rgba(0, 0, 0, 0.3)'
| }
| },
| ...getAnimationConfig()
| }
| ],
| dataZoom: props.showDataZoom
| ? [
| {
| type: 'inside',
| start: props.dataZoomStart,
| end: props.dataZoomEnd
| },
| {
| show: true,
| type: 'slider',
| top: '90%',
| start: props.dataZoomStart,
| end: props.dataZoomEnd
| }
| ]
| : void 0
| }
| }
| })
| </script>
|
|