|
@@ -5,137 +5,139 @@
|
|
<div v-if="!spinning" ref="chartRef" :style="{ height, width }"></div>
|
|
<div v-if="!spinning" ref="chartRef" :style="{ height, width }"></div>
|
|
</template>
|
|
</template>
|
|
<script lang="ts">
|
|
<script lang="ts">
|
|
- import { defineComponent, PropType, ref, Ref, reactive, watchEffect, watch, nextTick } from 'vue';
|
|
|
|
- import { useECharts } from '/@/hooks/web/useECharts';
|
|
|
|
- import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
|
|
|
|
- import EchartsUtil from '/@/utils/echartsUtil';
|
|
|
|
- import { merge } from 'lodash-es';
|
|
|
|
- type ChartColumn = {
|
|
|
|
- legend: string;
|
|
|
|
- seriesName: string;
|
|
|
|
- ymax: number;
|
|
|
|
- yname: string;
|
|
|
|
- linetype: string;
|
|
|
|
- yaxispos: string;
|
|
|
|
- color: string;
|
|
|
|
- sort: number;
|
|
|
|
- xRotate: number;
|
|
|
|
- dataIndex: string;
|
|
|
|
- };
|
|
|
|
- export default defineComponent({
|
|
|
|
- name: 'BarAndLine',
|
|
|
|
- props: {
|
|
|
|
- chartsColumns: {
|
|
|
|
- type: Array as PropType<ChartColumn[]>,
|
|
|
|
- default: () => [],
|
|
|
|
- },
|
|
|
|
- chartsColumnsType: {
|
|
|
|
- type: String,
|
|
|
|
- },
|
|
|
|
- chartsType: {
|
|
|
|
- type: String,
|
|
|
|
- default: '',
|
|
|
|
- },
|
|
|
|
- dataSource: {
|
|
|
|
- type: Array,
|
|
|
|
- default: () => [],
|
|
|
|
- },
|
|
|
|
- option: {
|
|
|
|
- type: Object,
|
|
|
|
- default: () => ({}),
|
|
|
|
- },
|
|
|
|
- xAxisPropType: {
|
|
|
|
- type: String,
|
|
|
|
- required: true,
|
|
|
|
- },
|
|
|
|
- width: {
|
|
|
|
- type: String as PropType<string>,
|
|
|
|
- default: '100%',
|
|
|
|
- },
|
|
|
|
- height: {
|
|
|
|
- type: String as PropType<string>,
|
|
|
|
- default: 'calc(100vh - 78px)',
|
|
|
|
- },
|
|
|
|
|
|
+import { defineComponent, PropType, ref, Ref, reactive, watchEffect, watch, nextTick } from 'vue';
|
|
|
|
+import { useECharts } from '/@/hooks/web/useECharts';
|
|
|
|
+import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
|
|
|
|
+import EchartsUtil from '/@/utils/echartsUtil';
|
|
|
|
+import { merge } from 'lodash-es';
|
|
|
|
+type ChartColumn = {
|
|
|
|
+ legend: string;
|
|
|
|
+ seriesName: string;
|
|
|
|
+ ymax: number;
|
|
|
|
+ yname: string;
|
|
|
|
+ linetype: string;
|
|
|
|
+ yaxispos: string;
|
|
|
|
+ color: string;
|
|
|
|
+ sort: number;
|
|
|
|
+ xRotate: number;
|
|
|
|
+ dataIndex: string;
|
|
|
|
+};
|
|
|
|
+export default defineComponent({
|
|
|
|
+ name: 'BarAndLine',
|
|
|
|
+ props: {
|
|
|
|
+ chartsColumns: {
|
|
|
|
+ type: Array as PropType<ChartColumn[]>,
|
|
|
|
+ default: () => [],
|
|
|
|
+ },
|
|
|
|
+ chartsColumnsType: {
|
|
|
|
+ type: String,
|
|
|
|
+ },
|
|
|
|
+ chartsType: {
|
|
|
|
+ type: String,
|
|
|
|
+ default: '',
|
|
|
|
+ },
|
|
|
|
+ dataSource: {
|
|
|
|
+ type: Array,
|
|
|
|
+ default: () => [],
|
|
},
|
|
},
|
|
- emits: ['refresh'],
|
|
|
|
- setup(props, { emit }) {
|
|
|
|
- const spinning = ref<boolean>(true);
|
|
|
|
- const chartRef = ref<HTMLDivElement | null>(null);
|
|
|
|
- const { setOptions, echarts } = useECharts(chartRef as Ref<HTMLDivElement>);
|
|
|
|
- const chartData = props.chartsColumnsType ? getTableHeaderColumns(props.chartsColumnsType) : [];
|
|
|
|
- let chartsColumns = (props.chartsColumns.length > 0 ? props.chartsColumns : chartData) as ChartColumn[];
|
|
|
|
- let tempYmax: number[] = [];
|
|
|
|
- let tempYmin: number[] = [];
|
|
|
|
- // let groupedByColumns = {};
|
|
|
|
- const option = reactive({
|
|
|
|
- name: '',
|
|
|
|
- color: ['#7B68EE', '#0000CD', '#6495ED', '#00BFFF', '#AFEEEE', '#008080', '#00FA9A', '#2E8B57', '#FAFAD2', '#DAA520'],
|
|
|
|
- tooltip: {},
|
|
|
|
- grid: {},
|
|
|
|
- toolbox: {
|
|
|
|
- feature: {
|
|
|
|
- saveAsImage: {
|
|
|
|
- iconStyle: {
|
|
|
|
- borderColor: '#ffffff',
|
|
|
|
- },
|
|
|
|
- show: false,
|
|
|
|
|
|
+ option: {
|
|
|
|
+ type: Object,
|
|
|
|
+ default: () => ({}),
|
|
|
|
+ },
|
|
|
|
+ xAxisPropType: {
|
|
|
|
+ type: String,
|
|
|
|
+ required: true,
|
|
|
|
+ },
|
|
|
|
+ width: {
|
|
|
|
+ type: String as PropType<string>,
|
|
|
|
+ default: '100%',
|
|
|
|
+ },
|
|
|
|
+ height: {
|
|
|
|
+ type: String as PropType<string>,
|
|
|
|
+ default: 'calc(100vh - 78px)',
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ emits: ['refresh'],
|
|
|
|
+ setup(props, { emit }) {
|
|
|
|
+ const spinning = ref<boolean>(true);
|
|
|
|
+ const chartRef = ref<HTMLDivElement | null>(null);
|
|
|
|
+ const { setOptions, echarts } = useECharts(chartRef as Ref<HTMLDivElement>);
|
|
|
|
+ const chartData = props.chartsColumnsType ? getTableHeaderColumns(props.chartsColumnsType) : [];
|
|
|
|
+ let chartsColumns = (props.chartsColumns.length > 0 ? props.chartsColumns : chartData) as ChartColumn[];
|
|
|
|
+ let tempYmax: number[] = [];
|
|
|
|
+ let tempYmin: number[] = [];
|
|
|
|
+ // let groupedByColumns = {};
|
|
|
|
+ const option = reactive({
|
|
|
|
+ name: '',
|
|
|
|
+ color: ['#7B68EE', '#0000CD', '#6495ED', '#00BFFF', '#AFEEEE', '#008080', '#00FA9A', '#2E8B57', '#FAFAD2', '#DAA520'],
|
|
|
|
+ tooltip: {},
|
|
|
|
+ grid: {},
|
|
|
|
+ toolbox: {
|
|
|
|
+ feature: {
|
|
|
|
+ saveAsImage: {
|
|
|
|
+ iconStyle: {
|
|
|
|
+ borderColor: '#ffffff',
|
|
},
|
|
},
|
|
|
|
+ show: false,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
- dataZoom: {},
|
|
|
|
- legend: {
|
|
|
|
- textStyle: {
|
|
|
|
- color: '#ffffff', // 字体颜色
|
|
|
|
- },
|
|
|
|
- top: '20',
|
|
|
|
|
|
+ },
|
|
|
|
+ dataZoom: {},
|
|
|
|
+ legend: {
|
|
|
|
+ textStyle: {
|
|
|
|
+ color: '#ffffff', // 字体颜色
|
|
},
|
|
},
|
|
- timeline: null,
|
|
|
|
- xAxis: {},
|
|
|
|
- yAxis: null,
|
|
|
|
- series: null,
|
|
|
|
- });
|
|
|
|
- let optionUtil;
|
|
|
|
|
|
+ top: '20',
|
|
|
|
+ },
|
|
|
|
+ timeline: null,
|
|
|
|
+ xAxis: {},
|
|
|
|
+ yAxis: null,
|
|
|
|
+ series: null,
|
|
|
|
+ });
|
|
|
|
+ let optionUtil;
|
|
|
|
|
|
- watchEffect(() => {
|
|
|
|
- props.dataSource && props.xAxisPropType && option.series && initCharts();
|
|
|
|
- });
|
|
|
|
|
|
+ watchEffect(() => {
|
|
|
|
+ props.dataSource && props.xAxisPropType && option.series && initCharts();
|
|
|
|
+ });
|
|
|
|
|
|
- watch([() => props.chartsType, () => props.chartsColumns], ([newChartsType, newChartsColumns]) => {
|
|
|
|
- spinning.value = true;
|
|
|
|
- chartsColumns = newChartsColumns;
|
|
|
|
- optionUtil.initChartOption(newChartsType, newChartsColumns);
|
|
|
|
- spinning.value = false;
|
|
|
|
- initCharts(true);
|
|
|
|
- emit('refresh');
|
|
|
|
- });
|
|
|
|
|
|
+ watch([() => props.chartsType, () => props.chartsColumns], ([newChartsType, newChartsColumns]) => {
|
|
|
|
+ spinning.value = true;
|
|
|
|
+ chartsColumns = newChartsColumns;
|
|
|
|
+ optionUtil.initChartOption(newChartsType, newChartsColumns);
|
|
|
|
+ spinning.value = false;
|
|
|
|
+ initCharts(true);
|
|
|
|
+ emit('refresh');
|
|
|
|
+ });
|
|
|
|
|
|
- function initChartsOption() {
|
|
|
|
- // debugger;
|
|
|
|
- optionUtil = new EchartsUtil(merge(option, props.option));
|
|
|
|
- optionUtil.initChartOption(props.chartsType, chartsColumns);
|
|
|
|
- }
|
|
|
|
- initChartsOption();
|
|
|
|
|
|
+ function initChartsOption() {
|
|
|
|
+ // debugger;
|
|
|
|
+ optionUtil = new EchartsUtil(merge(option, props.option));
|
|
|
|
+ optionUtil.initChartOption(props.chartsType, chartsColumns);
|
|
|
|
+ }
|
|
|
|
+ initChartsOption();
|
|
|
|
|
|
- function initCharts(isRefresh = false) {
|
|
|
|
- if (props.dataSource.length < 1) return;
|
|
|
|
- //轴数据
|
|
|
|
- let isFresh = false;
|
|
|
|
- if (option.series && option.series.length === chartsColumns.length) {
|
|
|
|
- let xAxisData = props.dataSource.map((item) => item[props.xAxisPropType]);
|
|
|
|
- chartsColumns = [...chartsColumns].filter((propType: any, index) => {
|
|
|
|
- if (!propType) return;
|
|
|
|
- if (props.chartsType == 'listMonitor') {
|
|
|
|
- option.series[index].type = 'bar';
|
|
|
|
- }
|
|
|
|
- option.series[index].data = props.dataSource.map((item) => Number(item[propType.dataIndex]) || 0);
|
|
|
|
- // console.log('nnn', option.series[index].data);
|
|
|
|
- // 这里动态计算echarts y轴最大值
|
|
|
|
- const max = Math.max(...option.series[index].data);
|
|
|
|
- const min = Math.min(...option.series[index].data);
|
|
|
|
- const digitCount = max.toFixed(0).length;
|
|
|
|
- const minDigitCount = min.toFixed(0).length;
|
|
|
|
- let yMax = 0,
|
|
|
|
- yMin = 0;
|
|
|
|
|
|
+ function initCharts(isRefresh = false) {
|
|
|
|
+ if (props.dataSource.length < 1) return;
|
|
|
|
+ //轴数据
|
|
|
|
+ let isFresh = false;
|
|
|
|
+ if (option.series && option.series.length === chartsColumns.length) {
|
|
|
|
+ let xAxisData = props.dataSource.map((item) => item[props.xAxisPropType]);
|
|
|
|
+ chartsColumns = [...chartsColumns].filter((propType: any, index) => {
|
|
|
|
+ if (!propType) return;
|
|
|
|
+ if (props.chartsType == 'listMonitor') {
|
|
|
|
+ option.series[index].type = 'bar';
|
|
|
|
+ }
|
|
|
|
+ console.log(option.series[index], '000===')
|
|
|
|
+ option.series[index].data = props.dataSource.map((item) => Number(item[propType.dataIndex]) || 0);
|
|
|
|
+ // console.log('nnn', option.series[index].data);
|
|
|
|
+ // 这里动态计算echarts y轴最大值
|
|
|
|
+ const max = Math.max(...option.series[index].data);
|
|
|
|
+ const min = Math.min(...option.series[index].data);
|
|
|
|
+ const digitCount = max.toFixed(0).length;
|
|
|
|
+ const minDigitCount = min.toFixed(0).length;
|
|
|
|
+ let yMax = 0,
|
|
|
|
+ yMin = 0;
|
|
|
|
+ if (option.series[index].name.indexOf('°C') == -1 && option.series[index].name.indexOf('%') == -1 ) {
|
|
if (digitCount < 2) {
|
|
if (digitCount < 2) {
|
|
if (max < 0.5) {
|
|
if (max < 0.5) {
|
|
yMax = 1;
|
|
yMax = 1;
|
|
@@ -213,85 +215,88 @@
|
|
yMin = 10000;
|
|
yMin = 10000;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- propType.ymax = yMax;
|
|
|
|
- propType.ymin = yMin;
|
|
|
|
- return true;
|
|
|
|
- });
|
|
|
|
- // debugger;
|
|
|
|
- // 根据sort分组
|
|
|
|
- const groupedBy = {};
|
|
|
|
- for (const item of chartsColumns) {
|
|
|
|
- if (groupedBy[item.sort]) {
|
|
|
|
- groupedBy[item.sort].push(item);
|
|
|
|
- } else {
|
|
|
|
- groupedBy[item.sort] = [item];
|
|
|
|
- }
|
|
|
|
|
|
+ } else {
|
|
|
|
+ yMax=100
|
|
|
|
+ yMin=0
|
|
}
|
|
}
|
|
- // 根据分组找ymax最大值
|
|
|
|
- const newChartsColumns: ChartColumn[] = [];
|
|
|
|
- let index = 0;
|
|
|
|
- for (let sortId in groupedBy) {
|
|
|
|
- const group = groupedBy[sortId];
|
|
|
|
- let ymax = group[0].ymax;
|
|
|
|
- let ymin = group[0].ymin;
|
|
|
|
- for (let i = 1; i < group.length; i++) {
|
|
|
|
- if (group[i].ymax > ymax) {
|
|
|
|
- ymax = group[i].ymax;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- for (let i = 1; i < group.length; i++) {
|
|
|
|
- if (group[i].ymin < ymin) {
|
|
|
|
- ymin = group[i].ymin;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (!tempYmax[index] || tempYmax[index] != ymax) {
|
|
|
|
- tempYmax[index] = ymax;
|
|
|
|
- isFresh = true;
|
|
|
|
- }
|
|
|
|
- if (tempYmin[index] != ymin) {
|
|
|
|
- tempYmin[index] = ymin;
|
|
|
|
- isFresh = true;
|
|
|
|
|
|
+ propType.ymax = yMax;
|
|
|
|
+ propType.ymin = yMin;
|
|
|
|
+ return true;
|
|
|
|
+ });
|
|
|
|
+ // debugger;
|
|
|
|
+ // 根据sort分组
|
|
|
|
+ const groupedBy = {};
|
|
|
|
+ for (const item of chartsColumns) {
|
|
|
|
+ if (groupedBy[item.sort]) {
|
|
|
|
+ groupedBy[item.sort].push(item);
|
|
|
|
+ } else {
|
|
|
|
+ groupedBy[item.sort] = [item];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 根据分组找ymax最大值
|
|
|
|
+ const newChartsColumns: ChartColumn[] = [];
|
|
|
|
+ let index = 0;
|
|
|
|
+ for (let sortId in groupedBy) {
|
|
|
|
+ const group = groupedBy[sortId];
|
|
|
|
+ let ymax = group[0].ymax;
|
|
|
|
+ let ymin = group[0].ymin;
|
|
|
|
+ for (let i = 1; i < group.length; i++) {
|
|
|
|
+ if (group[i].ymax > ymax) {
|
|
|
|
+ ymax = group[i].ymax;
|
|
}
|
|
}
|
|
- for (let i = 0; i < group.length; i++) {
|
|
|
|
- group[i].ymax = ymax;
|
|
|
|
- group[i].ymin = ymin;
|
|
|
|
- newChartsColumns.push(group[i]);
|
|
|
|
|
|
+ }
|
|
|
|
+ for (let i = 1; i < group.length; i++) {
|
|
|
|
+ if (group[i].ymin < ymin) {
|
|
|
|
+ ymin = group[i].ymin;
|
|
}
|
|
}
|
|
- ++index;
|
|
|
|
}
|
|
}
|
|
- chartsColumns = newChartsColumns;
|
|
|
|
- option.xAxis[0].data = xAxisData;
|
|
|
|
- if (isFresh) {
|
|
|
|
- spinning.value = true;
|
|
|
|
- optionUtil.initChartOption(props.chartsType, chartsColumns);
|
|
|
|
- spinning.value = false;
|
|
|
|
- initCharts(true);
|
|
|
|
- nextTick(() => {
|
|
|
|
- setOptions(option, true);
|
|
|
|
- emit('refresh');
|
|
|
|
- });
|
|
|
|
- } else {
|
|
|
|
- // console.log('echarts监测列表数据', option.xAxis[0].data);
|
|
|
|
- setOptions(option, isRefresh);
|
|
|
|
|
|
+ if (!tempYmax[index] || tempYmax[index] != ymax) {
|
|
|
|
+ tempYmax[index] = ymax;
|
|
|
|
+ isFresh = true;
|
|
|
|
+ }
|
|
|
|
+ if (tempYmin[index] != ymin) {
|
|
|
|
+ tempYmin[index] = ymin;
|
|
|
|
+ isFresh = true;
|
|
}
|
|
}
|
|
|
|
+ for (let i = 0; i < group.length; i++) {
|
|
|
|
+ group[i].ymax = ymax;
|
|
|
|
+ group[i].ymin = ymin;
|
|
|
|
+ newChartsColumns.push(group[i]);
|
|
|
|
+ }
|
|
|
|
+ ++index;
|
|
|
|
+ }
|
|
|
|
+ chartsColumns = newChartsColumns;
|
|
|
|
+ option.xAxis[0].data = xAxisData;
|
|
|
|
+ if (isFresh) {
|
|
|
|
+ spinning.value = true;
|
|
|
|
+ optionUtil.initChartOption(props.chartsType, chartsColumns);
|
|
|
|
+ spinning.value = false;
|
|
|
|
+ initCharts(true);
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ setOptions(option, true);
|
|
|
|
+ emit('refresh');
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ // console.log('echarts监测列表数据', option.xAxis[0].data);
|
|
setOptions(option, isRefresh);
|
|
setOptions(option, isRefresh);
|
|
}
|
|
}
|
|
|
|
+ setOptions(option, isRefresh);
|
|
}
|
|
}
|
|
- setTimeout(() => {
|
|
|
|
- spinning.value = false;
|
|
|
|
- initCharts(true);
|
|
|
|
- }, 1000);
|
|
|
|
- return { chartRef, spinning };
|
|
|
|
- },
|
|
|
|
- });
|
|
|
|
|
|
+ }
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ spinning.value = false;
|
|
|
|
+ initCharts(true);
|
|
|
|
+ }, 1000);
|
|
|
|
+ return { chartRef, spinning };
|
|
|
|
+ },
|
|
|
|
+});
|
|
</script>
|
|
</script>
|
|
<style lang="less" scoped>
|
|
<style lang="less" scoped>
|
|
- .spinning {
|
|
|
|
- display: flex;
|
|
|
|
- width: 100%;
|
|
|
|
- height: 100%;
|
|
|
|
- justify-content: center;
|
|
|
|
- align-items: center;
|
|
|
|
- }
|
|
|
|
|
|
+.spinning {
|
|
|
|
+ display: flex;
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ align-items: center;
|
|
|
|
+}
|
|
</style>
|
|
</style>
|