echart图表+表格实现显示上图下表,并动态加载数据,多接口异步处理

echart图表+表格实现显示上图下表,并动态加载数据,多接口异步处理

gitee地址:源码

介绍

以下是一个动态echart实现页面,可以实现echart多次接口请求同步处理效果,可实现js实时更新数据,折线图柱状图数量可以根据后端获取的数据动态调整,效果如图

在这里插入图片描述

首先说下页面的整体流程吧
  1. 第一步获取前置数据,从后端获取要显示的数据格式(这里我代码里直接用假数据替代了),用来告诉echart显示数据组的信息,比如示例图中就是显示两条折线一个柱状,数据格式如下:
    let dbData = [
        { name: '综合厂用电率(实际)', indexCode: '6000100261', type: 'line'},
        { name: '综合厂用电率(同期)', indexCode: '6000100261', type: 'line'},
        { name: '综合厂用电率(计划3)', indexCode: '6000100261', type: 'bar'},
    ]
	//name:数据组名称
	//indexCode:此数据组的编码,用来获取数据组的数据,我这个图标是通过编码获取1月到12月的数据
	//type:数据在图标上的呈现类型‘line’是折线,‘bar’是柱状图
  1. 第二步构造数据,通过刚才的dbData列表进行遍历,同时通过后端接口获取对应的数据组,构造echart渲染数据,我使用的是for循环遍历,遍历的同时进行异步处理防止在数据构造完成之前表格就开始渲染导致数据不显示的情况。具体细节看下方代码吧。
  2. 第三步渲染表格,等到所有数据据都构造完成后进行表格渲染
模拟接口安装教程
  1. 安装python,方法自行百度吧,教程比较多的
  2. cmd窗口进入到app.py所在的目录
  3. 安装flask
pip install flask
pip install flask_cors
  1. 运行app.py
python app.py

这样模拟接口就搭建好了运行成功后cmd窗口如图
在这里插入图片描述

然后直接浏览器打开动态表格.html就可以le
关于页面的具体实现都写在注释里了自己去研究吧

动态表格.html

<html>
<head>
    <title>动态获取数据</title>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.0.2/dist/echarts.min.js"></script>
    <script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>

</head>
<body>
<div class="mini-fit">
    <div id="_splTreeMain" class="mini-splitter" style="width:100%;height:100%;">
        <div id="jyjx">
            <div id="run_container">
                <div id="run_left-container">
                    <div class="run_left-section">
<!--&lt;!&ndash;   实际只用到了run_chart这一个元素其他的排版可忽略!!!!!!!!!!!  -->
                        <div id="run_chart" style="width: 1000px;height: 800px"></div>
                    </div>
                    <div class="run_left-section">

                    </div>
<!--                    <%&#45;&#45;        <div class="run_left-section">左侧下</div>&#45;&#45;%>-->
                </div>

                <div id="run_right-container">
                    <div class="run_right-section"></div>
                    <div class="run_right-section"></div>
<!--                    <%&#45;&#45;        <div class="run_right-section">右侧下</div>&#45;&#45;%>-->
<!--                    <%&#45;&#45;        <div class="run_right-section">右侧下</div>&#45;&#45;%>-->
                </div>
            </div>

        </div>
    </div>
</div>

<script type="text/javascript">







    //数据库的数据转json
    let dbData = [
        { name: '综合厂用电率(实际)', indexCode: '6000100261', type: 'line'},
        { name: '综合厂用电率(同期)', indexCode: '6000100261', type: 'line'},
        { name: '综合厂用电率(计划3)', indexCode: '6000100261', type: 'bar'},
    ]


    //生成表格
    initChart(dbData, "表格名称")


//自动获取每个月份的最后一天并生成字符串,在请求时作为参数,目前没用到可忽略
    // function getLastDayOfMonth(year, month) {
    //     // 构造下个月的第0天,即当前月的最后一天
    //     const lastDay = new Date(year, month + 1, 0);
    //     //console.log(lastDay, year, month)
    //
    //     // 获取年、月、日
    //     const yyyy = lastDay.getFullYear();
    //     const mm = (lastDay.getMonth() + 1).toString().padStart(2, '0'); // 月份从0开始,需要加1
    //     const dd = lastDay.getDate().toString().padStart(2, '0');
    //
    //     // 返回日期字符串
    //     return yyyy + `-` + mm + `-` + dd;
    // }
    //
    // function generateLastDaysOfYear(year) {
    //     const months = [];
    //     for (let month = 0; month < 12; month++) {
    //         const lastDayOfMonth = getLastDayOfMonth(year, month);
    //         console.log(lastDayOfMonth)
    //         months.push(lastDayOfMonth);
    //     }
    //     return months;
    // }
    //
    // const currentYear = new Date().getFullYear();
    // const lastDaysOfYear = generateLastDaysOfYear(currentYear);

    //console.log(lastDaysOfYear.join(','));



    //数据库的数据进行json规范化处理只保留字母数字以及,:'"{}[]()()这些些符号,上边已经直接声明了模拟数据所以这个函数没用到
    // function filterSpecialCharacters(inputString) {
    //     // 使用正则表达式匹配不是字母、数字和汉字的字符,并替换为空格
    //     return inputString.replace(/[^\w\d\u4e00-\u9fa5,:'"{}\[\]()()]+/g, '');
    // }


    //进行表格的初始化
    function initChart(dbData, title){
        //获取图标元素
        var myChart = echarts.init(document.getElementById('run_chart'));
        //x轴月份数据
        let datax = [ "1月", "2月", "3月", "4月", "5月", "6月", "7月",  "8月", "9月", "10月", "11月 ", "12月",]


        //根据dbData初始化图例信息
        let datal = dbData.map(function (item){return { 'name': item.name, 'icon': 'rect'}
        })

        //从后端接口获取的数据
        let datat = [];
        let datas = [];
        //因为我的使用场景是从一个接口获取三组不同数据所以需要处理一下同步问题,有条件可以走一个接口的就不需要他了
        let promises = [];

        //x坐标的通用属性,因为我想实现显示多行x轴数据所以只能把这个也搞成动态的了
        let xa = [{

            data: datax,

            axisLine: {

                show: true, //隐藏X轴轴线

                lineStyle: {

                    color: "#ffffff",

                    width: 0,

                },

            },

            axisTick: {

                show: false, //隐藏X轴刻度

                alignWithLabel: true,

            },

            axisLabel: {

                show: true,

                textStyle: {

                    color: "#000000", //X轴文字颜色

                    fontSize: 14,

                },

                interval: 0,

            },

        },];

        //图表数据颜色,目前只加了五个所以只支持最多五类数据显示,需要显示更多的话自己往列表里加颜色吧
        let colors = ['#ff0000', '#0078ff', '#ffd280', '#2c2c2c', '#11ff00' ];

        //###################以上为数据准备区,其中的数据可以根据自己的需求更改################


        // // 显示加载动画
        myChart.showLoading();

        for (let i = 0; i < dbData.length; i++) {
            let promise = new Promise((resolve, reject) => {
                $.ajax({
                    //我的ip就不暴露了返回数据类型如下
                    //[{date: "2023-01-31 00:00:00", indexCode: "6000100261", params: {}, value: 10896},
                    // {date: "2023-02-28 00:00:00", indexCode: "6000100261", params: {}, value: 6722},
                    // {date: "2023-03-31 00:00:00", indexCode: "6000100261", params: {}, value: 8826},
                    // {date: "2023-04-30 00:00:00", indexCode: "6000100261", params: {}, value: 11013},
                    // {date: "2023-05-31 00:00:00", indexCode: "6000100261", params: {}, value: 3870},
                    // {date: "2023-06-30 00:00:00", indexCode: "6000100261", params: {}, value: 4864},
                    // {date: "2023-07-31 00:00:00", indexCode: "6000100261", params: {}, value: 2944},
                    // {date: "2023-08-31 00:00:00", indexCode: "6000100261", params: {}, value: 3846},
                    // {date: "2023-09-30 00:00:00", indexCode: "6000100261", params: {}, value: 1074},
                    // {date: "2023-10-31 00:00:00", indexCode: "6000100261", params: {}, value: 2421},
                    // {date: "2023-11-30 00:00:00", indexCode: "6000100261", params: {}, value: 500},
                    // {date: "2023-12-31 00:00:00", indexCode: "6000100261", params: {}, value: 10859}]
                    //其实必要的只有value属性其他都没用到
                    //自己去构造一个测试接口或者用假数据测试吧,我是用python的flask搭建的文件一起上传到项目里了,安装好python直接运行.py文件就好了超简单,参数是indexCode和dates,格式如下
                    url: "http://localhost:5000/dataList?indexCode="+ dbData[i].indexCode +"&dates=2023-01-31,2023-02-28,2023-03-31,2023-04-30,2023-05-31,2023-06-30,2023-07-31,2023-08-31,2023-09-30,2023-10-31,2023-11-30,2023-12-31",
                    type: "get",
                    dataType: "json",
                    success: function (res) {
                        let data = res.map(x => x.value);
                        datas[i] = data;
                        datat.push({
                            'name': dbData[i].name,
                            'type': dbData[i].type,
                            'showSymbol': false,
                            'lineStyle': {
                                'color': colors[i],
                                'width': 4
                            },
                            'itemStyle': {
                                'color': colors[i],
                            },
                            'data': data,
                        });
                        xa.push({
                            position: 'bottom',
                            offset: 54 + 30 * i,
                            axisPointer: { type: 'none' },
                            axisLine: {
                                show: true, //隐藏X轴轴线
                                lineStyle: {
                                    color: "#ffffff",
                                    width: 0,
                                },
                            },
                            axisLabel: {
                                inside: true,
                                textStyle: {
                                    fontSize: '14',
                                    color: '#000000'
                                },
                                interval: 0,
                            },
                            data: datas[i],
                        })
                        resolve();
                    },
                    error: function (error) {
                        reject(error);
                    }
                });
            });

            promises.push(promise);
        }

        // 等待所有请求完成,因为上面是循环请求有几组数据就请求几次所以要做同步处理,不需要获取多次的话直接把所有同步相关的去掉就可以了
        Promise.all(promises)
            .then(() => {
                console.log("All requests completed");
                console.log(datat);
                console.log(datas);

                let option = {

                    title : {
                        show: true, //显示策略,默认值true,可选为:true(显示) | false(隐藏)
                        text: title, //主标题文本,'\n'指定换行
                        //link: '', //主标题文本超链接,默认值true
                        //target: null, //指定窗口打开主标题超链接,支持'self' | 'blank',不指定等同为'blank'(新窗口)
                        // subtext: '副标题', //副标题文本,'\n'指定换行
                        //sublink: '', //副标题文本超链接
                        //subtarget: null, //指定窗口打开副标题超链接,支持'self' | 'blank',不指定等同为'blank'(新窗口)
                        x: 'center', //水平安放位置,默认为'left',可选为:'center' | 'left' | 'right' | {number}(x坐标,单位px)
                        y: 'top', //垂直安放位置,默认为top,可选为:'top' | 'bottom' | 'center' | {number}(y坐标,单位px)
                        textAlign: null,//水平对齐方式,默认根据x设置自动调整,可选为: left' | 'right' | 'center
                        backgroundColor: 'rgba(0,0,0,0)', //标题背景颜色,默认'rgba(0,0,0,0)'透明
                        borderColor: '#ccc', //标题边框颜色,默认'#ccc'
                        borderWidth: 0, //标题边框线宽,单位px,默认为0(无边框)
                        padding: 5, //标题内边距,单位px,默认各方向内边距为5,接受数组分别设定上右下左边距
                        //itemGap: 10, //主副标题纵向间隔,单位px,默认为10
                        textStyle: { //主标题文本样式{"fontSize": 18,"fontWeight": "bolder","color": "#333"}
                            //fontFamily: 'Arial, Verdana, sans...',
                            fontSize: 28,
                            fontStyle: 'normal',
                            fontWeight: 'normal',
                        },
                    },

                    tooltip: {
                        trigger: 'axis'
                    },

                    grid: {

                        left: "18%",

                        top: "10%",

                        right: "0%",

                        bottom: "45%",

                    },

                    legend: {

                        align: "left",

                        itemGap: 17,

                        orient: "vertical",


                        bottom: 246 - (dbData.length - 3) * 29,

                        left: 0,

                        textStyle: {

                            color: "#000000", //X轴文字颜色

                            fontSize: 14,

                        },

                        // data: [ "问题总计", "已整改","整改中", "已整改占比",],

                        data: datal,

                    },

                    xAxis: xa,

                    yAxis: {
                        type: 'value'
                    },

                    series: datat,

                };

                // // 显示加载动画
                // myChart.showLoading();

                myChart.hideLoading();
                //使用刚指定的配置项和数据显示图表。
                myChart.setOption(option);

                console.log(myChart)

                // 进行数据渲染
                // 调用渲染函数等
            })
            .catch((error) => {
                console.error("Error in one or more requests:", error);
            });
    }



</script>
<style>

    #run_container {
        display: flex;
        height: 906px;
        width: 1244px;
    }

    #run_left-container {
        flex: 4;
        display: flex;
        flex-direction: column;
    }

    .run_left-section {
        flex: 1;
        background-color: #ffffff; /* 左侧上、中、下三段的背景颜色 */
        border: 1px solid #ffffff; /* 为了更好的展示效果添加边框 */
        box-sizing: border-box;
    }

    #run_right-container {
        flex: 1;
        display: flex;
        flex-direction: column;
    }

    .run_right-section {
        flex: 1;
        background-color: #ffffff; /* 右侧上、中、下三段的背景颜色 */
        border: 1px solid #ffffff; /* 为了更好的展示效果添加边框 */
        box-sizing: border-box;
    }

    #run_chart {
        height: 800px;
        width: 1000px;
        margin-top: 20px;
    }

</style>
</body>
</html>



app.py
from flask import Flask, request, jsonify
from flask_cors import CORS  # 导入 Flask-CORS
import random

app = Flask(__name__)
CORS(app)  # 启用 CORS 支持,允许任何来源的跨域请求


@app.route('/dataList', methods=['GET'])
def get_multiple_dates_index_value():
    index_code = request.args.get('indexCode', '')
    dates = request.args.get('dates', '').split(',')

    data = []
    for date in dates:
        data.append({
            "params": {},
            "date": date + " 00:00:00",
            "indexCode": index_code,
            "value": int(random.uniform(1, 11111))  # Set the value based on actual data
        })

    return jsonify(data)


if __name__ == '__main__':
    app.run(debug=True)

gitee的readme文件里有联系方式,有问题可联系我免费帮忙调试

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值