1
2 天以前 3a4a8c78098f41d3a7ce41f272cdefc35b572681
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>