使用自定义代码,添加echarts图表插件,统计图保存时报错问题该如何处理

背景&操作步骤

做了什么操作后,出现的该问题

  1. 添加自定义的测试数据代码后保存报错 this.subscribeEvent(“afterRender”, async () => {

            this.subscribeEvent("afterRender", async () => {
    
                const dom = document.getElementById("wlcs");
    
    
    
                if (!dom) {
    
                    console.error("未找到 id 为 'wlcs' 的容器元素");
    
                    return;
    
                }
    
    
    
                if (typeof echarts === "undefined") {
    
                    console.error("未检测到 echarts 库,请确保已引入");
    
                    return;
    
                }
    
    
    
                const myChart = echarts.init(dom);
    
    
    
                const rawDataLevel1 = \[{
    
                    "f_WewvDx": "物:W",
    
                    "f_QhGdnB": 160000
    
                }\];
    
    
    
                const rawDataLevel2 = \[{
    
                    "f_WewvDx": "物:W",
    
                    "f_JtciPs": "设备:SB",
    
                    "f_QhGdnB": 80000
    
                }, {
    
                    "f_WewvDx": "物:W",
    
                    "f_JtciPs": "设备:SS",
    
                    "f_QhGdnB": 0
    
                }, {
    
                    "f_WewvDx": "物:W",
    
                    "f_JtciPs": "香料:XL",
    
                    "f_QhGdnB": 80000
    
                }\];
    
    
    
                const buildChartData = (
    
                    currentData,
    
                    parentGroupId,
    
                    currentFieldKey,
    
                    nextLevelData,
    
                    nextLevelParentKey
    
                ) => {
    
                    let filteredData = currentData;
    
    
    
                    if (parentGroupId !== null) {
    
                        filteredData = currentData.filter(item => item\[nextLevelParentKey\] === parentGroupId);
    
                    }
    
    
    
                    return filteredData.map(item => {
    
                        const label = item\[currentFieldKey\];
    
                        const value = item.f_QhGdnB || 0;
    
                        const groupId = label;
    
                        let childGroupId = null;
    
    
    
                        if (nextLevelData && nextLevelData.length > 0) {
    
                            const hasChildren = nextLevelData.some(childItem => childItem\[nextLevelParentKey\] === groupId);
    
    
    
                            if (hasChildren) {
    
                                childGroupId = groupId;
    
                            }
    
                        }
    
    
    
                        return \[label, value, groupId, childGroupId\];
    
                    });
    
                };
    
    
    
                const createOption = (title, data, isRoot) => {
    
                    return {
    
                        id: isRoot ? "things" : data\[0\]\[2\],
    
    
    
                        title: {
    
                            text: title,
    
                            left: "center"
    
                        },
    
    
    
                        xAxis: {
    
                            type: "category",
    
                            name: "项目"
    
                        },
    
    
    
                        yAxis: {
    
                            type: "value",
    
                            minInterval: 1
    
                        },
    
    
    
                        series: {
    
                            type: "bar",
    
                            dimensions: \["x", "y", "groupId", "childGroupId"\],
    
    
    
                            encode: {
    
                                x: "x",
    
                                y: "y",
    
                                itemGroupId: "groupId",
    
                                itemChildGroupId: "childGroupId"
    
                            },
    
    
    
                            data: data,
    
    
    
                            universalTransition: {
    
                                enabled: true,
    
                                divideShape: "clone"
    
                            },
    
    
    
                            label: {
    
                                show: true,
    
                                position: "top",
    
                                formatter: "{c}"
    
                            }
    
                        },
    
    
    
                        graphic: isRoot ? \[\] : \[{
    
                            type: "text",
    
                            left: 50,
    
                            top: 20,
    
    
    
                            style: {
    
                                text: "Back",
    
                                fontSize: 18,
    
                                fill: "grey",
    
                                cursor: "pointer"
    
                            },
    
    
    
                            onclick: () => goBack()
    
                        }\]
    
                    };
    
                };
    
    
    
                const optionStack = \[\];
    
    
    
                const goForward = (nextLevelData, currentGroupId, currentFieldKey) => {
    
                    const nextData = buildChartData(rawDataLevel2, currentGroupId, currentFieldKey, null, "");
    
    
    
                    if (nextData.length === 0) {
    
                        console.log("无子数据");
    
                        return;
    
                    }
    
    
    
                    const currentOpt = myChart.getOption();
    
    
    
                    if (currentOpt && currentOpt.id) {
    
                        optionStack.push(currentOpt.id);
    
                    }
    
    
    
                    const newOption = createOption(\`子分类统计 - ${currentGroupId}\`, nextData, false);
    
                    myChart.setOption(newOption);
    
                };
    
    
    
                const goBack = () => {
    
                    if (optionStack.length === 0) {
    
                        console.log("已在根节点");
    
                        return;
    
                    }
    
    
    
                    const prevId = optionStack.pop();
    
    
    
                    if (prevId === "things") {
    
                        const rootData = buildChartData(rawDataLevel1, null, "f_WewvDx", rawDataLevel2, "f_WewvDx");
    
                        const rootOption = createOption("根分类统计", rootData, true);
    
                        myChart.setOption(rootOption);
    
                    } else {
    
                        console.log("简单模式下仅支持返回根节点,如需多级返回需扩展缓存逻辑");
    
                        const rootData = buildChartData(rawDataLevel1, null, "f_WewvDx", rawDataLevel2, "f_WewvDx");
    
                        const rootOption = createOption("根分类统计", rootData, true);
    
                        myChart.setOption(rootOption);
    
                        optionStack.length = 0;
    
                    }
    
                };
    
    
    
                const rootData = buildChartData(rawDataLevel1, null, "f_WewvDx", rawDataLevel2, "f_WewvDx");
    
                const rootOption = createOption("根分类统计", rootData, true);
    
                myChart.setOption(rootOption);
    
    
    
                myChart.on("click", "series", params => {
    
                    const dataItem = params.data;
    
                    const childGroupId = dataItem\[3\];
    
    
    
                    if (childGroupId) {
    
                        const nextFieldKey = "f_JtciPs";
    
                        goForward(rawDataLevel2, childGroupId, nextFieldKey);
    
                    } else {
    
                        console.log("已是最后一层");
    
                    }
    
                });
    
    
    
                window.addEventListener("resize", () => {
    
                    myChart.resize();
    
                });
    
            });
    
        });
    

问题

页面截图

前端控制台错误截图 (如果只是后端问题,可跳过)

接口返回数据截图 & 后端日志错误提示(如只是前端问题,可跳过)

期望效果

保存成功,图表可正常显示

这个看上去像是当前的echarts版本不支持这么写。我们项目当前的echarts版本是 5.4.3

就加了这句echarts就报错,不加是正常啊。

试试这样导入,新建个单独的文件 echarts.ts 内容如下:

/**
 * ECharts 按需导入配置
 * 只导入必要的图表类型和组件,减小打包体积
 */

import * as echarts from 'echarts/core';
import { BarChart, LineChart, PieChart, HeatmapChart } from 'echarts/charts';
import {
    TitleComponent,
    TooltipComponent,
    GridComponent,
    LegendComponent,
    VisualMapComponent,
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';

// 注册必要的组件
echarts.use([
    BarChart,
    LineChart,
    PieChart,
    HeatmapChart,
    TitleComponent,
    TooltipComponent,
    GridComponent,
    LegendComponent,
    VisualMapComponent,
    CanvasRenderer,
]);

export { echarts };

然后使用的时候导入

import { echarts } from './echarts';


echarts.init(domRef)

还可以试试直接导入线上的包

import * as echarts from "https://esm.sh/echarts@5.4.3?bundle"

导入线上的代码保存不报错了,但页面还是报错

看起来像是dom传入echarts中,你可以在page.ts 235行加一个debugger,看看现场的环境变量有什么问题

好像是没找到wlcs这个dom, let dom = document.getElementById(“wlcs”);为null

那你要看看是不是代码的生命周期不对,此时页面还没有渲染出dom

不太会这个该怎么操作

代码贴出来看看

import type { ComponentPageScheme } from “jit”;

import { Jit } from “jit”;

import schemeJson from “./scheme.json”;

import BlankComponent1 from “./BlankComponent1”;

type BaseComponent = InstanceType;

import * as echarts from “https://esm.sh/echarts@5.4.3?bundle”;

class PageCls extends Jit.GridPage {

Button2!: BaseComponent;

BlankComponent1!: BaseComponent = new BlankComponent1();

scheme: ComponentPageScheme = schemeJson;



bindEvent() {

    this.subscribeEvent("afterRender", async () => {

        const rawDataLevel1 = \[{

            "f_WewvDx": "物:W",

            "f_QhGdnB": 160000

        }\];



        const rawDataLevel2 = \[{

            "f_WewvDx": "物:W",

            "f_JtciPs": "设备:SB",

            "f_QhGdnB": 80000

        }, {

            "f_WewvDx": "物:W",

            "f_JtciPs": "设备:SS",

            "f_QhGdnB": 0

        }, {

            "f_WewvDx": "物:W",

            "f_JtciPs": "香料:XL",

            "f_QhGdnB": 80000

        }\];



        const buildChartData = (

            currentData,

            parentGroupId,

            currentFieldKey,

            nextLevelData,

            nextLevelParentKey

        ) => {

            let filteredData = currentData;



            if (parentGroupId !== null) {

                filteredData = currentData.filter(item => item\[nextLevelParentKey\] === parentGroupId);

            }



            return filteredData.map(item => {

                const label = item\[currentFieldKey\];

                const value = item.f_QhGdnB || 0;

                const groupId = label;

                let childGroupId = null;



                if (nextLevelData && nextLevelData.length > 0) {

                    const hasChildren = nextLevelData.some(childItem => childItem\[nextLevelParentKey\] === groupId);



                    if (hasChildren) {

                        childGroupId = groupId;

                    }

                }



                return \[label, value, groupId, childGroupId\];

            });

        };



        const optionStack = \[\];

        const optionsCache = {};



        const getRootOption = () => {

            const key = "root";



            if (optionsCache\[key\])

                return optionsCache\[key\];



            const data = buildChartData(rawDataLevel1, null, "f_WewvDx", rawDataLevel2, "f_WewvDx");



            const opt = {

                id: "root",



                title: {

                    text: "根分类统计",

                    left: "center"

                },



                xAxis: {

                    type: "category",

                    name: "项目"

                },



                yAxis: {

                    type: "value",

                    minInterval: 1

                },



                series: {

                    id: "main-series",

                    type: "bar",

                    dimensions: \["x", "y", "groupId", "childGroupId"\],



                    encode: {

                        x: "x",

                        y: "y",

                        itemGroupId: "groupId",

                        itemChildGroupId: "childGroupId"

                    },



                    data: data,



                    universalTransition: {

                        enabled: true,

                        divideShape: "clone"

                    },



                    label: {

                        show: true,

                        position: "top",

                        formatter: "{c}"

                    }

                }

            };



            optionsCache\[key\] = opt;

            return opt;

        };



        const getChildOption = (parentId, parentLabel) => {

            const key = "child\_" + parentId;



            if (optionsCache\[key\])

                return optionsCache\[key\];



            const data = buildChartData(rawDataLevel2, parentId, "f_JtciPs", null, "");



            const opt = {

                id: key,



                title: {

                    text: \`子分类统计 - ${parentLabel}\`,

                    left: "center"

                },



                xAxis: {

                    type: "category",

                    name: "细分项目"

                },



                yAxis: {

                    type: "value",

                    minInterval: 1

                },



                series: {

                    id: "main-series",

                    type: "bar",

                    dimensions: \["x", "y", "groupId", "childGroupId"\],



                    encode: {

                        x: "x",

                        y: "y",

                        itemGroupId: "groupId",

                        itemChildGroupId: "childGroupId"

                    },



                    data: data,



                    universalTransition: {

                        enabled: true,

                        divideShape: "clone"

                    },



                    label: {

                        show: true,

                        position: "top",

                        formatter: "{c}"

                    }

                },



                graphic: {

                    type: "text",

                    left: 50,

                    top: 20,



                    style: {

                        text: "← 返回",

                        fontSize: 16,

                        fill: "#666",

                        cursor: "pointer"

                    },



                    onclick: () => {

                        myChart.setOption(getRootOption());



                        while (optionStack.length > 0)

                            optionStack.pop();

                    }

                }

            };



            optionsCache\[key\] = opt;

            return opt;

        };



        let dom = document.getElementById("wlcs");



        if (!dom) {

            await new Promise(resolve => setTimeout(resolve, 100));

            dom = document.getElementById("wlcs");

        }



        const myChart = echarts.init(dom);

        myChart.setOption(getRootOption());

        myChart.resize();

        myChart.off("click");



        myChart.on("click", "series", params => {

            const dataItem = params.data;

            const childGroupId = dataItem\[3\];



            if (childGroupId) {

                optionStack.push(myChart.getOption().id);

                const parentLabel = dataItem\[0\];

                const newOption = getChildOption(childGroupId, parentLabel);

                myChart.setOption(newOption);

            } else {

                console.log("已是最后一层");

            }

        });

    });



    this.Button2.subscribeEvent("click", async () => {

        const Tql1 = this.app.modules.DataHandler.tableSet({

            "title": "数据集1",

            "dataType": "Tql",

            "tStr": "Select(\[F(\\"f_WewvDx\\"), F(Formula(\\"COLSUM(F('f_qHShfC'))\\"), \\"f_QhGdnB\\", \\"项目费用(Sum)\\", {\\"dataType\\":\\"Numeric\\",\\"decimal\\":1})\], From(\[Select(\[F(\\"T_yacntG.id\\", \\"f_mJBpLn\\"), F(\\"T_yacntG.category\\", \\"f_WewvDx\\"), F(\\"T_yacntG.levelI\\", \\"f_JtciPs\\"), F(\\"T_yacntG.levelIi\\", \\"f_sHZxfg\\"), F(\\"T_onWxHu.id\\", \\"f_SgseXC\\"), F(\\"T_onWxHu.titleOfTheProject1\\", \\"f_Tbeyxt\\"), F(\\"T_onWxHu.costs\\", \\"f_qHShfC\\")\], From(\[Select(\[F(\\"id\\"), F(\\"category\\"), F(\\"levelI\\"), F(\\"levelIi\\"), F(\\"levelIii\\"), F(\\"level4\\"), F(\\"level5\\"), F(\\"encoding\\"), F(\\"associatedItems\\")\], From(\[\\"models.materialSchedules\\", \\"T_Ulrfjd\\"\])), \\"T_yacntG\\"\], LeftJoin(Select(\[F(\\"id\\"), F(\\"itemNumber\\"), F(\\"titleOfTheProject1\\"), F(\\"typeOfProject\\"), F(\\"projectElements\\"), F(\\"areaName\\"), F(\\"factor\\"), F(\\"process\\"), F(\\"methodology\\"), F(\\"otherOrganiser\\"), F(\\"endDate\\"), F(\\"typeOfProduct\\"), F(\\"natureOfUnits\\"), F(\\"nameOfUnit\\"), F(\\"capitalBudget\\"), F(\\"costBudget\\"), F(\\"projectBudget\\"), F(\\"costs\\"), F(\\"projectStatus\\"), F(\\"projectCategory\\"), F(\\"projectManager\\"), F(\\"projectFocalPoints\\"), F(\\"core\\"), F(\\"principalPersonnel\\"), F(\\"participants\\"), F(\\"sector\\"), F(\\"typeOfArea\\"), F(\\"modalitiesOfImplementation\\"), F(\\"typeOfProductInTheProductionProc\\"), F(\\"factor1\\"), F(\\"process1\\"), F(\\"logisticsLevelClassification\\"), F(\\"secondaryClassificationOfLogisti\\"), F(\\"equipmentLevelClassification\\"), F(\\"equipmentLevelIiClassification\\"), F(\\"levelIiiClassificationOfEquipmen\\")\], From(\[\\"models.itemTable\\", \\"T_UrBNLO\\"\])),\\"T_onWxHu\\"), On(\[F(\\"T_yacntG.associatedItems\\"), \\"=\\", F(\\"T_onWxHu.id\\")\])), \\"横向连接\\"), \\"T_rWvmQR\\"\]), GroupBy(F(\\"f_WewvDx\\")), \\"分组汇总\\")",

            "dataSources": {},

            "previewDataSources": {}

        });



        const data = await Tql1.getRowList(undefined);

        console.log("查到的数据", data);

    });

}

}

export default PageCls;

import { Jit } from ‘jit’;

import { Button, message } from ‘antd’;

// 自定义组件的实现包括:渲染器和逻辑处理类

// Render是自定义组件的渲染器,UI部分在这里实现,它是一个React组件

const Render = (props) => {

// 渲染器接收一个实例对象compIns,是下面BlankComponent1的实例对象,

const compIns = props.compIns;



const handleClick = () => {

    // 调用compIns获取数据

    message.success(compIns.getData());



    // 通过publishEvent方法触发事件,页面中可订阅该事件

    compIns.publishEvent('handleClickMe');

    // 订阅事件可以在page.ts中全代码写,在page的bindEvent方法中加入这段:

    // this.BlankComponent1.subscribeEvent("handleClickMe", async () => {

    //    // TODO 收到该事件后的具体实现

    // });

    // 如果希望通过GUI配置该事件订阅,在scheme.json中componentList找到对应组件配置,在eventList中添加一个事件声明:

    //    {

    //        ...

    //        "componentList":\[

    //            "name": "BlankComponent1",  // 实际情况中需要把BlankComponent1换成真实的组件类名

    //            ...

    //            {

    //                ...

    //                "eventList": \[

    //                  {

    //                      "title": "点击行",       // 事件标题

    //                      "name": "handleClickMe", // 事件名称

    //                  }

    //                \]

    //           }

    //        \]

    //    }

};



 return (

    <div style={{display:'flex',width:'100%',height:'100%'}}>

    <div id="wlcs" style={{height:'100%',width:'100%'}}>

    </div>

    </div>

);

};

// 这是自定义组件逻辑处理类,逻辑部分在这里实现,它是一个javascript的class

export default class BlankComponent1 extends Jit.BaseComponent {

// 将自定义组件的渲染器挂载到组件逻辑对象上

Render = Render;



/\*\*

 \* 获取数据,组件的方法, 页面及页面中的其它组件可以调用该方法

 \*/

getData() {

    // 这里可以做更多的事情,比如请求后端接口

    return 'so cool !!!';

}



// 如果需要在GUI配置调用该方法,需要再在scheme.json中componentList找到对应组件配置,在functionList中添加一个方法声明

//    {

//        ...

//        "componentList":\[

//            "name": "BlankComponent1",  // 实际情况中需要把BlankComponent1换成真实的组件类名

//            ...

//            {

//                ...

//                "functionList": \[

//                  {

//                      "title": "获取数据",   // 函数标题

//                      "name": "getData",    // 函数name

//                      "args": \[\],           // 函数参数

//                      "returnType": ""      // 返回值类型

//                  }

//                \]

//           }

//        \]

//    }

}

尝试把渲染逻辑移到自定义组件的这个生命周期试试看

page.ts里面呢? 之前的代码不用修改是吧?

关于图标渲染的代码移到自定义组件就好了

该如何修改调整

有谁能帮忙远程看一下呢?

此问题该怎么处理呢?有没有人可以解决下

有没有人处理

报错显示page.ts 的260行25列有问题,你的需求是要用自定义的组件使用echart画一个统计图吗