1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 08:19:15 +08:00

feat: 封装echart组件之line组件

This commit is contained in:
wangdan 2023-03-08 10:43:00 +08:00 committed by wangdan-fit2cloud
parent e88437e7cd
commit 60c2eef8ed
5 changed files with 379 additions and 159 deletions

View File

@ -75,6 +75,7 @@ declare module 'vue' {
Footer: typeof import('./src/components/app-layout/footer/index.vue')['default'] Footer: typeof import('./src/components/app-layout/footer/index.vue')['default']
Group: typeof import('./src/components/group/index.vue')['default'] Group: typeof import('./src/components/group/index.vue')['default']
InfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll'] InfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll']
Line: typeof import('./src/components/v-charts/components/Line.vue')['default']
Loading: typeof import('element-plus/es')['ElLoadingDirective'] Loading: typeof import('element-plus/es')['ElLoadingDirective']
Logo: typeof import('./src/components/app-layout/menu/components/Logo.vue')['default'] Logo: typeof import('./src/components/app-layout/menu/components/Logo.vue')['default']
Menu: typeof import('./src/components/app-layout/menu/index.vue')['default'] Menu: typeof import('./src/components/app-layout/menu/index.vue')['default']
@ -85,6 +86,7 @@ declare module 'vue' {
SvgIcon: typeof import('./src/components/svg-icon/svg-icon.vue')['default'] SvgIcon: typeof import('./src/components/svg-icon/svg-icon.vue')['default']
TableSetting: typeof import('./src/components/table-setting/index.vue')['default'] TableSetting: typeof import('./src/components/table-setting/index.vue')['default']
Upload: typeof import('./src/components/upload/index.vue')['default'] Upload: typeof import('./src/components/upload/index.vue')['default']
VCharts: typeof import('./src/components/v-charts/index.vue')['default']
} }
} }

View File

@ -0,0 +1,152 @@
<template>
<div :id="id" class="v-charts" ref="chartRef" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, nextTick, watch } from 'vue';
import * as echarts from 'echarts';
import { GlobalStore } from '@/store';
const globalStore = GlobalStore();
const props = defineProps({
id: {
type: String,
default: 'VChartsId',
},
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: '200px',
},
type: {
type: String,
default: 'line',
},
option: {
type: Object,
required: true,
}, // option: { title , xDatas, yDatas, formatStr }
});
function initChart() {
let itemChart = echarts?.getInstanceByDom(document.getElementById(props.id) as HTMLElement);
//
if (itemChart == null) {
itemChart = echarts.init(document.getElementById(props.id) as HTMLElement);
}
const theme = globalStore.$state.themeConfig.theme || 'light';
//
const option = {
title: [
{
left: 'center',
text: props.option.title,
show: false,
},
],
zlevel: 1,
z: 1,
tooltip: {
trigger: 'axis',
formatter: function (datas: any) {
let res = datas[0].name + '<br/>';
for (const item of datas) {
res += item.marker + ' ' + item.seriesName + '' + item.data + props.option.formatStr + '<br/>';
}
return res;
},
},
grid: { left: '7%', right: '7%', bottom: '20%' },
legend: {
data: [props.option?.yDatas[0]?.name, props.option?.yDatas[1]?.name],
right: 10,
itemWidth: 8,
textStyle: {
color: '#646A73',
},
icon: 'circle',
},
xAxis: { data: props.option.xDatas, boundaryGap: false },
yAxis: {
name: '( ' + props.option.formatStr + ' )',
splitLine: {
//线
lineStyle: {
type: 'dashed', //线 线0
opacity: theme === 'dark' ? 0.1 : 1, //
},
},
},
series: [
{
name: props.option?.yDatas[0]?.name,
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(0, 94, 235, .5)',
},
{
offset: 1,
color: 'rgba(0, 94, 235, 0)',
},
]),
},
data: props.option?.yDatas[0]?.data,
showSymbol: false,
},
{
name: props.option?.yDatas[1]?.name,
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(27, 143, 60, .5)',
},
{
offset: 1,
color: 'rgba(27, 143, 60, 0)',
},
]),
},
data: props.option?.yDatas[1]?.data,
showSymbol: false,
},
],
dataZoom: [{ startValue: props?.option.xDatas[0] }],
};
//
itemChart.setOption(option, true);
window.onresize = function () {
//
itemChart.resize();
};
}
watch(
() => props.option,
(val) => {
if (val) {
nextTick(() => {
initChart();
});
}
},
);
onMounted(() => {
nextTick(() => {
initChart();
});
});
onUnmounted(() => {
echarts.dispose;
});
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,23 @@
<template>
<component :is="typeComponentMap[type]" :height="height" :option="option" />
</template>
<script lang="ts" setup>
import line from './components/Line.vue';
defineOptions({ name: 'VCharts' });
defineProps({
type: {
type: String,
default: 'line',
},
height: {
type: String,
default: '200px',
},
option: {
type: Object,
required: true,
}, // { title , xDatas, yDatas, formatStr }
});
const typeComponentMap = { line };
</script>

View File

@ -106,16 +106,23 @@
</el-tag> </el-tag>
<el-tag>{{ $t('home.rwPerSecond') }}: {{ currentInfo.ioTime }} ms</el-tag> <el-tag>{{ $t('home.rwPerSecond') }}: {{ currentInfo.ioTime }} ms</el-tag>
</div> </div>
<div
v-if="chartOption === 'io'" <div v-if="chartOption === 'io'" style="margin-top: 40px">
id="ioChart" <v-charts
style="margin-top: 40px; width: 100%; height: 300px" height="300px"
></div> id="ioChart"
<div :option="chartsOption['ioChart']"
v-if="chartOption === 'network'" v-if="chartsOption['ioChart']"
id="networkChart" />
style="margin-top: 40px; width: 100%; height: 300px" </div>
></div> <div v-if="chartOption === 'network'" style="margin-top: 40px">
<v-charts
height="300px"
id="networkChart"
:option="chartsOption['networkChart']"
v-if="chartsOption['networkChart']"
/>
</div>
</div> </div>
</template> </template>
</CardWithHeader> </CardWithHeader>
@ -188,9 +195,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, onBeforeUnmount, ref, reactive } from 'vue'; import { onMounted, onBeforeUnmount, ref, reactive } from 'vue';
import * as echarts from 'echarts'; // import * as echarts from 'echarts';
import Status from '@/views/home/status/index.vue'; import Status from '@/views/home/status/index.vue';
import App from '@/views/home/app/index.vue'; import App from '@/views/home/app/index.vue';
import VCharts from '@/components/v-charts/index.vue';
import CardWithHeader from '@/components/card-with-header/index.vue'; import CardWithHeader from '@/components/card-with-header/index.vue';
import i18n from '@/lang'; import i18n from '@/lang';
import { Dashboard } from '@/api/interface/dashboard'; import { Dashboard } from '@/api/interface/dashboard';
@ -199,8 +207,8 @@ import { useRouter } from 'vue-router';
import RouterButton from '@/components/router-button/index.vue'; import RouterButton from '@/components/router-button/index.vue';
import { loadBaseInfo, loadCurrentInfo } from '@/api/modules/dashboard'; import { loadBaseInfo, loadCurrentInfo } from '@/api/modules/dashboard';
import { getIOOptions, getNetworkOptions } from '@/api/modules/monitor'; import { getIOOptions, getNetworkOptions } from '@/api/modules/monitor';
import { GlobalStore } from '@/store'; // import { GlobalStore } from '@/store';
const globalStore = GlobalStore(); // const globalStore = GlobalStore();
const router = useRouter(); const router = useRouter();
const statuRef = ref(); const statuRef = ref();
@ -300,6 +308,8 @@ const currentChartInfo = reactive({
netBytesRecv: 0, netBytesRecv: 0,
}); });
const chartsOption = ref({ ioChart1: null, networkChart: null });
const changeOption = async () => { const changeOption = async () => {
isInit.value = true; isInit.value = true;
loadData(); loadData();
@ -338,7 +348,7 @@ const onLoadBaseInfo = async (isInit: boolean, range: string) => {
statuRef.value.acceptParams(currentInfo.value, baseInfo.value); statuRef.value.acceptParams(currentInfo.value, baseInfo.value);
appRef.value.acceptParams(baseInfo.value); appRef.value.acceptParams(baseInfo.value);
if (isInit) { if (isInit) {
window.addEventListener('resize', changeChartSize); // window.addEventListener('resize', changeChartSize);
timer = setInterval(async () => { timer = setInterval(async () => {
onLoadCurrentInfo(); onLoadCurrentInfo();
}, 3000); }, 3000);
@ -436,160 +446,193 @@ function loadUpTime(uptime: number) {
const loadData = async () => { const loadData = async () => {
if (chartOption.value === 'io') { if (chartOption.value === 'io') {
let ioReadYDatas = { const yDatas = [
name: i18n.global.t('monitor.read'), {
type: 'line', name: i18n.global.t('monitor.read'),
areaStyle: { data: ioReadBytes.value,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(27, 143, 60, 1)',
},
{
offset: 1,
color: 'rgba(27, 143, 60, 0)',
},
]),
}, },
data: ioReadBytes.value, {
showSymbol: false, name: i18n.global.t('monitor.write'),
}; data: ioWriteBytes.value,
let ioWriteYDatas = {
name: i18n.global.t('monitor.write'),
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(0, 94, 235, 1)',
},
{
offset: 1,
color: 'rgba(0, 94, 235, 0)',
},
]),
}, },
data: ioWriteBytes.value, ];
showSymbol: false, chartsOption.value['ioChart'] = {
title: i18n.global.t('home.io'),
xDatas: timeIODatas.value,
yDatas: yDatas,
formatStr: 'MB',
}; };
freshChart(
'ioChart', // let ioReadYDatas = {
[i18n.global.t('monitor.read'), i18n.global.t('monitor.write')], // name: i18n.global.t('monitor.read'),
timeIODatas.value, // type: 'line',
[ioReadYDatas, ioWriteYDatas], // areaStyle: {
i18n.global.t('home.io'), // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
'MB', // {
); // offset: 0,
// color: 'rgba(27, 143, 60, 1)',
// },
// {
// offset: 1,
// color: 'rgba(27, 143, 60, 0)',
// },
// ]),
// },
// data: ioReadBytes.value,
// showSymbol: false,
// };
// let ioWriteYDatas = {
// name: i18n.global.t('monitor.write'),
// type: 'line',
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: 'rgba(0, 94, 235, 1)',
// },
// {
// offset: 1,
// color: 'rgba(0, 94, 235, 0)',
// },
// ]),
// },
// data: ioWriteBytes.value,
// showSymbol: false,
// };
// freshChart(
// 'ioChart',
// [i18n.global.t('monitor.read'), i18n.global.t('monitor.write')],
// timeIODatas.value,
// [ioReadYDatas, ioWriteYDatas],
// i18n.global.t('home.io'),
// 'MB',
// );
} else { } else {
let netTxYDatas = { const yDatas = [
name: i18n.global.t('monitor.up'), {
type: 'line', name: i18n.global.t('monitor.up'),
areaStyle: { data: netBytesRecvs.value,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(0, 94, 235, .5)',
},
{
offset: 1,
color: 'rgba(0, 94, 235, 0)',
},
]),
}, },
data: netBytesRecvs.value, {
showSymbol: false, name: i18n.global.t('monitor.down'),
}; data: netBytesSents.value,
let netRxYDatas = {
name: i18n.global.t('monitor.down'),
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(27, 143, 60, .5)',
},
{
offset: 1,
color: 'rgba(27, 143, 60, 0)',
},
]),
}, },
data: netBytesSents.value, ];
showSymbol: false, chartsOption.value['networkChart'] = {
title: i18n.global.t('home.network'),
xDatas: timeNetDatas.value,
yDatas: yDatas,
formatStr: 'KB/s',
}; };
freshChart( // let netTxYDatas = {
'networkChart', // name: i18n.global.t('monitor.up'),
[i18n.global.t('monitor.up'), i18n.global.t('monitor.down')], // type: 'line',
timeNetDatas.value, // areaStyle: {
[netTxYDatas, netRxYDatas], // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
i18n.global.t('home.network'), // {
'KB/s', // offset: 0,
); // color: 'rgba(0, 94, 235, .5)',
// },
// {
// offset: 1,
// color: 'rgba(0, 94, 235, 0)',
// },
// ]),
// },
// data: netBytesRecvs.value,
// showSymbol: false,
// };
// let netRxYDatas = {
// name: i18n.global.t('monitor.down'),
// type: 'line',
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: 'rgba(27, 143, 60, .5)',
// },
// {
// offset: 1,
// color: 'rgba(27, 143, 60, 0)',
// },
// ]),
// },
// data: netBytesSents.value,
// showSymbol: false,
// };
// freshChart(
// 'networkChart',
// [i18n.global.t('monitor.up'), i18n.global.t('monitor.down')],
// timeNetDatas.value,
// [netTxYDatas, netRxYDatas],
// i18n.global.t('home.network'),
// 'KB/s',
// );
} }
}; };
function freshChart(chartName: string, legendDatas: any, xDatas: any, yDatas: any, yTitle: string, formatStr: string) { // function freshChart(chartName: string, legendDatas: any, xDatas: any, yDatas: any, yTitle: string, formatStr: string) {
if (isInit.value) { // if (isInit.value) {
echarts.init(document.getElementById(chartName) as HTMLElement); // echarts.init(document.getElementById(chartName) as HTMLElement);
isInit.value = false; // isInit.value = false;
} // }
let itemChart = echarts.getInstanceByDom(document.getElementById(chartName) as HTMLElement); // let itemChart = echarts.getInstanceByDom(document.getElementById(chartName) as HTMLElement);
const theme = globalStore.$state.themeConfig.theme || 'light'; // const theme = globalStore.$state.themeConfig.theme || 'light';
const option = { // const option = {
title: [ // title: [
{ // {
left: 'center', // left: 'center',
text: yTitle, // text: yTitle,
show: false, // show: false,
}, // },
], // ],
zlevel: 1, // zlevel: 1,
z: 1, // z: 1,
tooltip: { // tooltip: {
trigger: 'axis', // trigger: 'axis',
formatter: function (datas: any) { // formatter: function (datas: any) {
let res = datas[0].name + '<br/>'; // let res = datas[0].name + '<br/>';
for (const item of datas) { // for (const item of datas) {
res += item.marker + ' ' + item.seriesName + '' + item.data + formatStr + '<br/>'; // res += item.marker + ' ' + item.seriesName + '' + item.data + formatStr + '<br/>';
} // }
return res; // return res;
}, // },
}, // },
grid: { left: '7%', right: '7%', bottom: '20%' }, // grid: { left: '7%', right: '7%', bottom: '20%' },
legend: { // legend: {
data: legendDatas, // data: legendDatas,
right: 10, // right: 10,
itemWidth: 8, // itemWidth: 8,
textStyle: { // textStyle: {
color: '#646A73', // color: '#646A73',
}, // },
icon: 'circle', // icon: 'circle',
}, // },
xAxis: { data: xDatas, boundaryGap: false }, // xAxis: { data: xDatas, boundaryGap: false },
yAxis: { // yAxis: {
name: '( ' + formatStr + ' )', // name: '( ' + formatStr + ' )',
splitLine: { // splitLine: {
//线 // //线
lineStyle: { // lineStyle: {
type: 'dashed', //线 线0 // type: 'dashed', //线 线0
opacity: theme === 'dark' ? 0.1 : 1, // // opacity: theme === 'dark' ? 0.1 : 1, //
}, // },
}, // },
}, // },
series: yDatas, // series: yDatas,
dataZoom: [{ startValue: xDatas[0] }], // dataZoom: [{ startValue: xDatas[0] }],
}; // };
itemChart?.setOption(option, true); // itemChart?.setOption(option, true);
} // }
function changeChartSize() { // function changeChartSize() {
if (document.getElementById('ioChart') != null) { // if (document.getElementById('ioChart') != null) {
echarts.getInstanceByDom(document.getElementById('ioChart') as HTMLElement)?.resize(); // echarts.getInstanceByDom(document.getElementById('ioChart') as HTMLElement)?.resize();
} // }
if (document.getElementById('networkChart') != null) { // if (document.getElementById('networkChart') != null) {
echarts.getInstanceByDom(document.getElementById('networkChart') as HTMLElement)?.resize(); // echarts.getInstanceByDom(document.getElementById('networkChart') as HTMLElement)?.resize();
} // }
} // }
onMounted(() => { onMounted(() => {
onLoadNetworkOptions(); onLoadNetworkOptions();
@ -600,7 +643,7 @@ onMounted(() => {
onBeforeUnmount(() => { onBeforeUnmount(() => {
clearInterval(Number(timer)); clearInterval(Number(timer));
timer = null; timer = null;
window.removeEventListener('resize', changeChartSize); // window.removeEventListener('resize', changeChartSize);
}); });
</script> </script>

View File

@ -37,7 +37,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
open: viteEnv.VITE_OPEN, open: viteEnv.VITE_OPEN,
proxy: { proxy: {
'/api/v1': { '/api/v1': {
target: 'http://localhost:9999/', target: 'http://172.16.10.181:9999/',
changeOrigin: true, changeOrigin: true,
}, },
}, },