123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- <template>
- <!-- 折线图 -->
- <div style="width: 100%; height: 100%">
- <div class="echartitem" style="width: 100%; height: 100%">
- <!-- <h3 class="selcal">{{ props.selval }}</h3> -->
- <div
- id="line2"
- ref="chartContainer"
- style="width: 100%; height: 100%"
- ></div>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, onMounted, reactive, markRaw, inject, watch, nextTick } from "vue"
- import { RouterView, RouterLink } from "vue-router"
- import { request, uploadFile } from "@/utils/request"
- import { ElMessage, ElButton, ElDialog, ElSelect } from "element-plus"
- import * as echarts from "echarts"
- let vars = ref([])
- let vals = ref([])
- let series = ref([])
- let xdata = ref([])
- let chartContainer = ref(null)
- let myChart
- let chartDom = ref()
- let option = ref(null)
- let convergeDate = ref([])
- let curvedata = ref("")
- let state = reactive({
- instance: null
- })
- const props = defineProps({
- echartdata: {
- type: String
- },
- curvedata: {
- type: String
- },
- echartLineshow: {
- type: Boolean,
- default: false
- }
- })
- onMounted(() => {
-
- myChart = echarts.init(chartContainer.value)
- linechart()
- myChart.resize();
- })
- // 监听 scattershow 变化
- watch(
- () => props.echartLineshow,
- (newValue) => {
- if (newValue) {
- nextTick(() => {
- const chartDom = chartContainer.value
- if (chartDom) {
- myChart = echarts.init(chartDom)
- myChart.resize() // 手动调整图表大小
- linechart()// 设置图表配置
- }
- })
- }
- },
- { immediate: true }
- )
- //初始化
- const echatinit = () => {
- convergeDate.value = []
- series.value = []
- xdata.value = []
- }
- // 从websocket取数据
- // const getsockechart=(data)=>{
- // curvedata.value=data;
- // series.value=[];
- // let rows=curvedata.value;
- // for(let i=0;i<rows.length;i++){
- // vars.value=(rows[i].vars).split(",");
- // vals.value=(rows[i].vals).split(" ");
- // let data= vals.value.map((str) => Number(str));
- // convergeDate.value.push(data);
- // xdata.value.push(rows[i].step);
- // }
- // for(let j=0;j<vars.value.length;j++){
- // let firstColumn=(convergeDate.value.map((row) => row[j]));
- // let item= {
- // name:vars.value[j] ,
- // type: 'line',
- // stack: 'Total',
- // data: firstColumn
- // }
- // series.value.push(item)
- // }
- // myChart.setOption({
- // legend: {
- // data:vars.value
- // },
- // xAxis:{
- // data: xdata.value,
- // },
- // series: series.value
- // });
- // }
- const getsockechart = (data) => {
- curvedata.value = data;
- convergeDate.value = [];
- series.value = [];
- xdata.value = [];
- let rows = JSON.parse(curvedata.value);
- if (!rows.length) return; // 处理空数据
- let varsList = rows[0].vars.split(","); // 提取变量名
- vars.value = varsList;
- // 解析数据
- rows.forEach((row, index) => {
- xdata.value.push(index + 1); // 直接填充 X 轴数据
- convergeDate.value.push(row.vals.split(" ").map(Number)); // 解析数值数组
- });
- // 生成 series 数据
- series.value = varsList.map((varName, j) => ({
- name: varName,
- type: "line",
- stack: "Total",
- symbol: "none",
- data: convergeDate.value.map(row => row[j]) // 获取每列数据
- }));
- // 更新图表
- myChart.setOption({
- legend: {
- data: vars.value,
- },
- xAxis: {
- type: "category",
- data: xdata.value,
- },
- yAxis: {
- type: "value",
- },
- series: series.value,
- });
- };
- // 绘制所有数据的曲线
- const getshuju = (dataheader, data) => {
- console.log("散点图曲线数据1:", data);
- curvedata.value = data;
- series.value = [];
- xdata.value = [];
- vars.value = dataheader; // dataheader 是包含 label 和 prop 的数组
- vals.value = data;
- // 生成 x 轴数据
- for (let i = 0; i < vals.value.length; i++) {
- xdata.value.push(i); // x 轴数据为行索引
- }
- // 为每个字段生成一条曲线
- for (let colIndex = 0; colIndex < vars.value.length; colIndex++) {
- const prop = vars.value[colIndex].prop; // 获取当前列的字段名
- const label = vars.value[colIndex].label; // 获取当前列的显示名称
- let seriesData = [];
- // 遍历每一行,提取该列的数据
- for (let rowIndex = 0; rowIndex < vals.value.length; rowIndex++) {
- let value = vals.value[rowIndex][prop]; // 获取当前列的值
- seriesData.push([xdata.value[rowIndex], value]); // 添加到 seriesData
- }
- // 为每列数据生成一条曲线,使用 label 作为曲线的名字
- series.value.push({
- name: label, // 使用 label 作为曲线名
- type: "line", // 散点图类型
- data: seriesData,
- });
- }
- // 处理 ECharts 图表配置
- const myChart = echarts.init(chartContainer.value);
- myChart.setOption({
- legend: {
- data: vars.value.map(item => item.label), // 图例数据是列名
- },
- xAxis: {
- type: "category", // 设置为 "category" 表示 x 轴为分类数据
- data: xdata.value, // x 轴数据为索引
- },
- yAxis: {
- type: "value", // y 轴是数值型
- },
- series: series.value, // 使用生成的 series 数据
- });
- console.log("初始化后的 series:", series.value);
- };
- const selectshuju = (listcbval,listcbval2,dataheader, data) => {
- console.log("图曲线数据1:", data);
- curvedata.value = data;
- series.value = [];
- xdata.value = [];
- const ydata = ref([]);
- vars.value = dataheader; // dataheader 是包含 label 和 prop 的数组
- vals.value = data; // vals 是表格数据
- console.log('listcbval',listcbval)
- console.log('listcbval2',listcbval2)
- // 生成 X 轴数据和 Y 轴数据
- const xColumns = listcbval; // 获取 listcbval 中选择的列,作为 X 轴
- const yColumns = listcbval2; // 获取 listcbval2 中选择的列,作为 Y 轴
- console.log('xColumns',xColumns)
- console.log('yColumns',yColumns)
- if (xColumns.length === 0 || yColumns.length === 0) {
- console.error('请先选择 X 轴和 Y 轴的变量');
- return;
- }
- // 遍历每一行数据,为每对 X 和 Y 轴选择的列生成数据
- for (let i = 0; i < vals.value.length; i++) {
- let xValue = [];
- let yValue = [];
- // 对于每个 X 轴选择的列,提取该列数据
- for (let xCol of xColumns) {
- let xColumnData = vals.value[i][xCol]; // 获取当前行的 X 列数据
- xValue.push(xColumnData);
- }
- // 对于每个 Y 轴选择的列,提取该列数据
- for (let yCol of yColumns) {
- let yColumnData = vals.value[i][yCol]; // 获取当前行的 Y 列数据
- yValue.push(yColumnData);
- }
- xdata.value.push(xValue);
- ydata.value.push(yValue);
- }
- // 为每个 Y 轴数据列生成一条曲线
- for (let yColIndex = 0; yColIndex < yColumns.length; yColIndex++) {
- const label = yColumns[yColIndex]; // 使用 Y 轴列名作为曲线的标签
- let seriesData = [];
- for (let rowIndex = 0; rowIndex < vals.value.length; rowIndex++) {
- let xValues = xdata.value[rowIndex]; // 获取当前行的 X 轴数据
- let yValue = ydata.value[rowIndex][yColIndex]; // 获取当前行的 Y 轴数据
- // 将 X 和 Y 的数据组成成对的数据,传给 seriesData
- for (let xVal of xValues) {
- seriesData.push([xVal, yValue]); // 每对 (X, Y) 数据
- }
- }
- // 生成曲线的数据
- series.value.push({
- name: label, // 使用列名作为曲线名
- type: "line", // 散点图类型
- data: seriesData,
- });
- }
- // 处理 ECharts 图表配置
- const myChart = echarts.init(chartContainer.value);
- const xAxisLabel = dataheader.find(item => item.prop === xColumns[0])?.label || xColumns[0];
- const yAxisLabel = getFormattedYLabels(yColumns, dataheader);
- const yAxisLabel1 = getFormattedYLabels1(yColumns, dataheader);
- const chartTitle = `${xAxisLabel} - ${yAxisLabel1}`;
- myChart.setOption({
- title: {
- text: chartTitle,
- },
- legend: {
- data: yColumns, // 图例数据使用 Y 轴的列名
- },
- xAxis: {
- type: "value",
- data: xdata.value, // x 轴数据为 X 轴数据
- name: xAxisLabel,
- scale: true,
- },
- yAxis: {
- type: "value", // y 轴是数值型
- name: yAxisLabel,
- scale: true,
- },
- series: series.value, // 使用生成的 series 数据
-
- });
- console.log("初始化后的 series:", series.value);
- };
- const getFormattedYLabels = (columns, header, maxLength = 20) => {
- const labels = columns.map(col => {
- return header.find(item => item.prop === col)?.label || col;
- });
- const fullLabel = labels.join(',\n');
- // 若总字符数超出 maxLength,则截断
- if (fullLabel.length > maxLength) {
- return fullLabel.slice(0, maxLength) + '...';
- }
- return fullLabel;
- };
- // 不换行
- const getFormattedYLabels1 = (columns, header, maxLength = 20) => {
- const labels = columns.map(col => {
- return header.find(item => item.prop === col)?.label || col;
- });
- const fullLabel = labels.join(',');
- // 若总字符数超出 maxLength,则截断
- if (fullLabel.length > maxLength) {
- return fullLabel.slice(0, maxLength) + '...';
- }
- return fullLabel;
- };
- const linechart = () => {
- option.value = {
- title: {
- text: " ",
- left: "center",
- top: "5%",
- textStyle: {
- color: "#333333",
- fontSize: 16,
- fontWeight: "normal",
- fontFamily:'Microsoft YaHei'
- }
- },
- tooltip: {
- trigger: "axis", //item
- backgroundColor: "rgba(0,0,0,.6)",
- borderColor: "rgba(147, 235, 248, .8)",
- textStyle: {
- color: "#FFF"
- }
- },
- legend: {
- data: vars.value,
- orient: "vertical", // 图例方向 (horizontal水平, vertical垂直)
- right: "0%",
- top: "2%",
- itemWidth: 30,
- pageButtonItemGap: 10,
- pageButtonPosition: 'end',
- type: 'scroll',
- },
- grid: {
- show: false,
- left: "5%",
- right: "14%",
- bottom: "10%",
- containLabel: true
- },
- // toolbox: {
- // feature: {
- // saveAsImage: {}
- // }
- // },
- xAxis: {
- type: "value",
- boundaryGap: false,
- name: "",
- nameGap:30,
- nameTextStyle:{
- fontSize: 16,
- color:'#333333',
- fontFamily:'Microsoft YaHei'
- },
- nameLocation: 'middle',
- data: xdata.value,
- axisLine: {
- //X轴线
- show: true,
- lineStyle: {
- color: "#333333", // 线的颜色
- width: 1, // 线宽
- type: "solid" // 线的类型,默认为实线,可选:'solid', 'dashed', 'dotted'
- }
- },
- splitLine: {
- show: true // 如果不需要网格线,可以设置为 false
- }
- },
- yAxis: {
- type: "value",
- name:"",
- nameGap:50,
- nameTextStyle:{
- fontsize:16,
- color:'#333333',
- fontFamily:'Microsoft YaHei'
- },
- nameLocation:"middle",
- axisTick: {
- show: true
- },
- splitLine: {
- show:true
- },
- axisLine: {
- //Y轴线
- show: true,
- lineStyle: {
- color: "#333333", // 线的颜色
- width: 1, // 线宽
- type: "solid" // 线的类型,默认为实线,可选:'solid', 'dashed', 'dotted'
- }
- }
- },
- dataZoom: [
- {
- type:"inside",
- xAxisIndex: [0],
- },
- {
- type:'slider',
- xAxisIndex: [0],
- show: false,
- },
- ],
- series: series.value
- }
- option.value && myChart.setOption(option.value)
- window.onresize = function () {
- // 让图表自适应大小
- myChart.resize()
- }
- }
- // 监听数据变化,重绘图表
- // watch( myChart.value, () => {
- // console.log(11111)
- // window.onresize = function() {
- // // 让图表自适应大小
- // myChart.value.resize();
- // };
- // });
- //window.addEventListener('resize', handleResize);
- // watch(series, () => {
- // linechart();
- // }, { deep: true });
- // watch(() =>props.echartdata, (newValue, oldValue) => {
- // // 这里处理 echartData 变化的逻辑
- // console.log(11111)
- // console.log('echartData changed:', newValue);
- // // console.log(optmonitor1.value);
- // }, {deep: true ,immediate: true });
- defineExpose({ linechart, getsockechart, echatinit ,getshuju,selectshuju})
- </script>
- <style lang="scss" scoped>
- .selcal {
- position: absolute;
- top: 37%;
- width: 26px;
- color: #000;
- font-size: 14px;
- font-weight: bold;
- left: 5px;
- }
- .diedai {
- color: #000;
- font-size: 14px;
- padding-bottom: 20px;
- font-weight: bold;
- }
- </style>
-
-
|