|
@@ -0,0 +1,268 @@
|
|
|
+<template>
|
|
|
+ <div ref="chartRef" :style="{height:height, width:width}"></div>
|
|
|
+ <p>{{ props.showMetrics }}</p>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
|
|
|
+import * as echarts from 'echarts'
|
|
|
+import XEUtils from 'xe-utils'
|
|
|
+
|
|
|
+defineOptions({
|
|
|
+ name: 'DataTendencyChart'
|
|
|
+})
|
|
|
+interface Props {
|
|
|
+ dataset: {[key: string]: any}[],
|
|
|
+ showMetrics: ShowMetric[],
|
|
|
+ width: string,
|
|
|
+ height: string
|
|
|
+}
|
|
|
+
|
|
|
+const props = withDefaults(defineProps<Props>(), { width: "100%", height: "500px" })
|
|
|
+const chartRef = ref()
|
|
|
+let chartObj:any
|
|
|
+const resizeChart = () => { chartObj.resize() }
|
|
|
+const addResize = () => { window.addEventListener('resize', resizeChart) }
|
|
|
+const removeResize = () => { window.removeEventListener('resize', resizeChart) }
|
|
|
+const option: {[key: string]: any} = {
|
|
|
+ dataset: {
|
|
|
+ source: props.dataset
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ axisPointer: {
|
|
|
+ type: 'cross',
|
|
|
+ label: {
|
|
|
+ backgroundColor: '#6a7985'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ selected: {}, // 控制显隐
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ top: 50, right: 150, bottom: 30, left: 55,
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'time'
|
|
|
+ },
|
|
|
+ yAxis: [
|
|
|
+ {
|
|
|
+ type: 'value',
|
|
|
+ name: '',
|
|
|
+ splitLine: {
|
|
|
+ show: true // 设置显示分割线
|
|
|
+ },
|
|
|
+ // axisLabel: {
|
|
|
+ // formatter: '{value}'
|
|
|
+ // },
|
|
|
+ axisLine: {
|
|
|
+ show: true
|
|
|
+ },
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'value',
|
|
|
+ name: '',
|
|
|
+ position: 'right',
|
|
|
+ splitLine: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ // axisLabel: {
|
|
|
+ // formatter: '{value} 单位2'
|
|
|
+ // },
|
|
|
+ axisLine: {
|
|
|
+ show: true
|
|
|
+ },
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'value',
|
|
|
+ position: 'right',
|
|
|
+ offset: 80,
|
|
|
+ name: '',
|
|
|
+ splitLine: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ // axisLabel: {
|
|
|
+ // formatter: '{value} 单位3'
|
|
|
+ // },
|
|
|
+ axisLine: {
|
|
|
+ show: true
|
|
|
+ },
|
|
|
+ show: false
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '',
|
|
|
+ type: 'bar',
|
|
|
+ encode: {
|
|
|
+ x: 'date',
|
|
|
+ y: ''
|
|
|
+ },
|
|
|
+ // tooltip: {
|
|
|
+ // valueFormatter: function (value) {
|
|
|
+ // return value + ' ml';
|
|
|
+ // }
|
|
|
+ // },
|
|
|
+ barWidth: '20px',
|
|
|
+ yAxisIndex: 0,
|
|
|
+ itemStyle: {
|
|
|
+ // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ // { offset: 0, color: 'rgba(111, 209, 206, 0.8)' },
|
|
|
+ // { offset: 1, color: 'rgba(111, 209, 206, 0.1)' },
|
|
|
+ // ]),
|
|
|
+ color: '',
|
|
|
+ //柱状图圆角
|
|
|
+ borderRadius: [15, 15, 0, 0],
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '',
|
|
|
+ type: 'line',
|
|
|
+ encode: {
|
|
|
+ x: 'date',
|
|
|
+ y: ''
|
|
|
+ },
|
|
|
+ symbolSize: 6,
|
|
|
+ symbol: 'circle',
|
|
|
+ smooth: true,
|
|
|
+ yAxisIndex: 1,
|
|
|
+ // lineStyle: { color: '#fe9a8b' },
|
|
|
+ itemStyle: { color: '#fe9a8b', borderColor: '#fe9a8b' },
|
|
|
+ areaStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ { offset: 0, color: '#fe9a8bb3' },
|
|
|
+ { offset: 1, color: '#fe9a8b03' },
|
|
|
+ ]),
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '',
|
|
|
+ type: 'line',
|
|
|
+ encode: {
|
|
|
+ x: 'date',
|
|
|
+ y: ''
|
|
|
+ },
|
|
|
+ symbolSize: 6,
|
|
|
+ symbol: 'circle',
|
|
|
+ smooth: true,
|
|
|
+ yAxisIndex: 2,
|
|
|
+ // lineStyle: { color: '#9E87FF' },
|
|
|
+ itemStyle: { color: '#9E87FF', borderColor: '#9E87FF' },
|
|
|
+ areaStyle: {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
+ { offset: 0, color: '#9E87FFb3' },
|
|
|
+ { offset: 1, color: '#9E87FF03' },
|
|
|
+ ]),
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ itemStyle: {
|
|
|
+ color: {
|
|
|
+ type: 'radial',
|
|
|
+ x: 0.5,
|
|
|
+ y: 0.5,
|
|
|
+ r: 0.5,
|
|
|
+ colorStops: [
|
|
|
+ { offset: 0, color: '#9E87FF' },
|
|
|
+ { offset: 0.4, color: '#9E87FF' },
|
|
|
+ { offset: 0.5, color: '#fff' },
|
|
|
+ { offset: 0.7, color: '#fff' },
|
|
|
+ { offset: 0.8, color: '#fff' },
|
|
|
+ { offset: 1, color: '#fff' },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ borderColor: '#9E87FF',
|
|
|
+ borderWidth: 2,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ initLine()
|
|
|
+ addResize()
|
|
|
+})
|
|
|
+onBeforeUnmount(() => {
|
|
|
+ if(chartObj) {
|
|
|
+ chartObj.dispose()
|
|
|
+ chartObj = null
|
|
|
+ }
|
|
|
+ removeResize()
|
|
|
+})
|
|
|
+watch(
|
|
|
+ props.showMetrics,
|
|
|
+ () => {
|
|
|
+ // const option: any = {
|
|
|
+ // legend: {
|
|
|
+ // selected: {},
|
|
|
+ // yAxis: [
|
|
|
+ // {name: '', show: false},
|
|
|
+ // {name: '', show: false},
|
|
|
+ // {name: '', show: false}
|
|
|
+ // ],
|
|
|
+ // series: [
|
|
|
+ // {name: '', encode: {y: ''}, itemStyle: {color: ''}},
|
|
|
+ // {name: '', encode: {y: ''}, itemStyle: {color: ''}},
|
|
|
+ // {name: '', encode: {y: ''}, itemStyle: {color: ''}}
|
|
|
+ // ]
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ const tmp:{[key: string]: boolean} = {}
|
|
|
+ for (const info of props.showMetrics) { tmp[info.metric] = true }
|
|
|
+ for (const key of XEUtils.keys(option.legend.selected)) {
|
|
|
+ if (XEUtils.has(tmp, key)) {
|
|
|
+ option.legend.selected[key] = true
|
|
|
+ } else {
|
|
|
+ option.legend.selected[key] = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (const [metricInfo, yInfo, sInfo] of XEUtils.zip(props.showMetrics, option.yAxis, option.series)) {
|
|
|
+ if (metricInfo) {
|
|
|
+ yInfo.name = metricInfo.label
|
|
|
+ yInfo.show = true
|
|
|
+
|
|
|
+ sInfo.name = metricInfo.label
|
|
|
+ sInfo.encode.y = metricInfo.metric
|
|
|
+ sInfo.itemStyle.color = metricInfo.color
|
|
|
+
|
|
|
+ } else {
|
|
|
+ yInfo.show = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log(option)
|
|
|
+
|
|
|
+ chartObj.setOption(option)
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+const initLine = () => {
|
|
|
+ chartObj = echarts.init(chartRef.value)
|
|
|
+
|
|
|
+ const tmp:{[key: string]: boolean} = {}
|
|
|
+ for (const info of props.showMetrics) { tmp[info.metric] = true }
|
|
|
+ option.legend.selected = tmp
|
|
|
+
|
|
|
+ props.showMetrics.forEach((info, index) => {
|
|
|
+ option.yAxis[index].name = info.label
|
|
|
+ option.yAxis[index].show = true
|
|
|
+
|
|
|
+ option.series[index].name = info.label
|
|
|
+ option.series[index].encode.y = info.metric
|
|
|
+ option.series[index].itemStyle.color = info.color
|
|
|
+ })
|
|
|
+ console.log(option)
|
|
|
+ chartObj.setOption(option)
|
|
|
+}
|
|
|
+
|
|
|
+defineExpose({resizeChart})
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+</style>
|