You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
5.5 KiB

<script lang="ts" setup>
import type { Ref } from 'vue'
import { onMounted, ref, watch } from 'vue'
import type { YAXisOption } from 'echarts/types/dist/shared'
import moment from 'moment'
import { Empty } from 'ant-design-vue'
import { useECharts } from '@/hooks/web/useECharts'
import { propTypes } from '@/utils/propTypes'
const props = defineProps({
isAsync: {
type: Boolean,
default: false,
},
height: {
type: String,
default: '500px',
},
width: {
type: String,
default: '100%',
},
title: {
type: String,
default: '',
},
name: {
type: Array as PropType<string[]>,
default: () => [],
},
data: {
type: Array as PropType<number[][]>,
default: () => [],
},
// height: propTypes.string.def('70vh'),
})
const chartRef = ref<HTMLDivElement | null>(null)
const { setOptions, setGroup, chartInstance } = useECharts(chartRef as Ref<HTMLDivElement>, 'default', props.isAsync)
onMounted(() => {
})
// const yAxis = reactive<yAxisForm>({
// type: 'value',
// scale: true, // 开启自适应刻度
// })
watch(
() => props.data,
() => {
console.log(props.data)
const yAxis = ref<YAXisOption[]>([])
const series = ref<any[]>([])
const title = ref<any>({})
for (let i = 0; i < props.data?.length; i++) {
title.value = {
left: 'left',
text: props.title,
show: true,
textStyle: { // 设置主标题的文字风格
fontFamily: 'sans-serif', // 字体系列
fontWeight: 350,
color: 'black', // 字体颜色
fontSize: 16, // 文字大小
},
}
yAxis.value.push({
type: 'value',
show: false,
scale: true, // 开启自适应刻度
})
series.value.push({
name: props.name?.[i] || '',
type: 'line',
smooth: true,
showSymbol: false,
data: props.data?.[i] || [],
yAxisIndex: i,
})
}
// const aa = getInstance()
setOptions({
// 网格
grid: {
x: '2%',
y: '5%',
x2: '2%',
y2: '10%',
containLabel: false,
// width: {totalWidth} - x - x2,
// height: {totalHeight} - y - y2,
backgroundColor: 'rgba(0,0,0,0)',
borderWidth: 1,
borderColor: '#ccc',
},
tooltip: {
trigger: 'axis',
position(pt) {
return [pt[0], '10%']
},
confine: true, // 添加此行,限制 tooltip 在图表容器内显示
backgroundColor: 'rgba(255, 255, 255, 0.5)', // ⭐ 透明度 0~1
},
title: title.value,
toolbox: {
feature: {
dataZoom: {
yAxisIndex: 'none',
},
restore: { show: false },
saveAsImage: {},
/* 自定义事件,注意:自定义事件必须以my开头 */
myTool2: {
show: true,
title: '下载csv文件', /* 鼠标停留时的提示文字 */
// icon: 'image://../0IMG/tool.png', /* 显示图标,必须以image://为开头显示后面是图表的路径 */
icon: 'path://M18 20.288L21.288 17l-.688-.688l-2.1 2.1v-4.887h-1v4.887l-2.1-2.1l-.688.688zM14.5 23.5v-1h7v1zm-10-4v-17H13L18.5 8v3.14h-1V8.5h-5v-5h-7v15h6.615v1zm1-1v-15z',
/* 点击时触发的事件 */
onclick() {
setTimeout(() => {
// 使用这个函数转换数据为CSV格式
const csv = convertToCSV(props.data)
console.log(props.data)
// 如果你想提供下载链接
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = 'data.csv'
link.click()
function convertToCSV(data) {
let csv = ''
// 添加列头
const name = props.name?.join(',') || ''
csv += `时间,${name}\n`
// 遍历数据并添加到CSV字符串中
for (let i = 0; i < props.data?.[0]?.length || 0; i++) {
let data = ''
for (let j = 0; j < props.data?.length || 0; j++)
data += `,${props.data?.[j]?.[i]?.[1] || ''}`
csv += `${moment(props.data?.[0]?.[i]?.[0] || 0).format('YYYY-MM-DD HH:mm:ss')}${data}\n`
// props.data[i].map((item, index) => {
// csv += 'x值' + ',' + 'y值' + '\n'
// })
}
return csv
}
}, 10)
},
},
},
},
xAxis: {
type: 'time',
axisTick: {
length: 6,
lineStyle: {
type: 'dashed',
},
},
// boundaryGap: false,
},
yAxis: yAxis.value,
legend: {
},
dataZoom: [
{
type: 'slider',
start: 0,
end: 100,
},
// 没有下面这块的话,只能拖动滚动条,
// 鼠标滚轮在区域内不能控制外部滚动条
// {
// start: 0,
// end: 100,
// },
],
series: series.value,
})
},
{ immediate: true },
)
</script>
<template>
<div v-if="name.length === 0" :style="{ width, height, display: 'flex', justifyContent: 'center', alignItems: 'center' }">
<Empty />
</div>
<div v-else ref="chartRef" :style="{ width, height }" />
</template>