Files
dvcp_v2_webapp/ui/packages/tools/AiEchartV2.vue
yanran200730 c16559ea1e 图表组件
2023-03-10 10:55:02 +08:00

229 lines
5.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<section class="AiEchart">
<div ref="AiEchart" class="chart" :style="{minWidth:grid.width,minHeight:grid.height}"/>
<slot v-if="$slots.default"/>
<render-component v-else-if="ops.render" :render="ops.render" :options="chartOptions" :data="data"/>
</section>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: "AiEchartV2",
props: {
data: {default: () => []},
ops: {default: () => ({})},
type: {default: "line"},
series: Object,
theme: {
default: '0'
}
},
components: {
renderComponent: {
functional: true,
props: {
render: Function,
options: {default: () => ({})},
data: {default: () => []}
},
render(h, ins) {
let {options = {}, data} = ins.props
return ins.props.render(h, {...options, data})
}
}
},
data() {
return {
chart: null,
timer: null
}
},
computed: {
colors() {
if (this.theme === '0') {
return ['#00F9FF', '#1890FF', '#B13BFF', '#FC3BFF', '#95FF44', '#ea7ccc']
}
return ['#D4380D', '#CF1322', '#D55800', '#FA8C16', '#FFC53D', '#FFA940', '#FFC53D', '#780000']
},
chartOptions() {
let {type, data, ops: options = {}} = this,
style = this.series ? this.series : this.ops.daemon ? this.ops.daemon : {},
colors = this.theme === '1' ? this.colors : (options.color || this.colors),
legend = {textStyle: {color: '#fff', padding: [0, 0, 0, 8], fontSize: 14}, show: false},
series = data?.[0] ? Array(Object.keys(data?.[0]).length - 1).fill(1)
.map((e, i) => ({type, ...(typeof style == 'object' ? style : style(colors[i]))})) : []
let ops = {
tooltip: {},
xAxis: {
type: 'category', nameGap: 20, axisTick: false,
axisLabel: {
color: '#C3C4C4',
interval: 0,
rotate: this.data.length > 10 ? 40 : 0
},
axisLine: {
lineStyle: {
color: this.theme === '1' ? 'rgba(239, 163, 51, 0.8)' : 'rgba(255,255,255,.5)',
width: 1
}
}
},
// 声明一个 Y 轴,数值轴。
yAxis: {
nameGap: 23, minInterval: 1,
splitLine: {
lineStyle: {
color: this.theme === '1' ? 'rgba(255, 197, 52, 0.4)' : 'rgba(255, 255, 255, .2)',
type: 'dashed'
}
},
axisLabel: { color: '#C3C4C4' },
axisLine: {
lineStyle: {
color: '#C3C4C4'
}
}
},
legend, series, ...options,
color: colors,
grid: {
left: '0%',
right: '0%',
bottom: '0%',
top: '40px',
containLabel: true
}
}
return ops
},
grid() {
let {width, height} = this.chartOptions.grid || {}
return {
width: width ? (width - this.legend === '1' ? 160 : 0) + 'px' : 'auto',
height: height ? height + 'px' : 'auto'
}
}
},
watch: {
data: {
deep: true, handler(v, old) {
let oldDims = Object.keys(old?.[0] || {})?.toString(),
current = Object.keys(v?.[0] || {})?.toString()
this.getChartData(oldDims != current)
}
},
theme() {
this.refresh()
}
},
methods: {
deepAssign() {
let name, options, src, copy
let length = arguments.length
// 记录要复制的对象的下标
let i = 1
// target默认是第一个参数
let target = arguments[0] || {}
// 如果target不是对象我们是无法进行复制的所以设为{}
if (typeof target !== 'object') {
target = {}
}
// 循环遍历要复制的对象
for (; i < length; i++) {
// 获取当前对象
options = arguments[i]
// 要求不能为空 避免extend(a,,b)这种情况
if (options != null) {
for (name in options) {
// 目标属性值
src = target[name]
// 要复制的对象的属性值
copy = options[name]
if (copy && typeof copy == 'object') {
// 递归调用
target[name] = this.deepAssign( src, copy)
} else if (copy !== undefined) {
target[name] = copy
}
}
}
}
return target
},
getChartData(render) {
if (!render) {
this.chart?.setOption({
dataset: {
source: this.data || []
}
})
} else {
this.chart?.setOption({
...this.chartOptions,
dataset: {
source: this.data || []
}
}, true)
}
},
initChart() {
this.chart = echarts.init(this.$refs.AiEchart)
this.chart.setOption(this.chartOptions || {})
},
watchResize() {
this.timer && clearInterval(this.timer)
this.timer = setInterval(() => {
if (this.chart?.getHeight() != this.$refs.AiEchart?.clientHeight ||
this.chart?.getWidth() != this.$refs.AiEchart?.clientWidth) {
this.chart?.resize()
}
}, 1000)
//5分钟后停止监听
setTimeout(() => this.timer && clearInterval(this.timer), 5 * 60 * 1000)
},
refresh() {
this.chart.setOption(this.chartOptions || {})
}
},
mounted() {
this.$nextTick(() => {
this.watchResize()
this.initChart()
this.getChartData()
})
console.log(this.data)
},
beforeDestroy() {
this.timer && clearInterval(this.timer)
}
}
</script>
<style lang="scss" scoped>
.AiEchart {
display: flex;
width: 100%;
height: 100%;
flex: 1;
min-width: 100px;
min-height: 0;
position: relative;
.chart {
flex: 1;
height: 100%;
min-height: 100px;
}
}
</style>