BOM树的构造

 

 

物料清单是是描述企业产品组成的技术文件。在加工资本式行业,它表明了产品的总装件、分装件、组件、部件、零件、直到原材料之间的结构关系,以及所需的数量。在化工、制药和食品行业产品组成则对主要原料、中间体、辅助材料及其配方和所需数量的说明。BOM是将用图表示的产品组成改用数据表格的形式表示出来,它是MRPII系统中计算MRP过程中的重要控制文件。

    ERP系统需求。本次版本的所有功能需求都是建立在老版本ERP之上的,所以本文档的功能需求以及业务逻辑完全COPY原来版本,而修改的是实现方式。

树的设计

首先,新建一个物料清单(以下简称BOM)的时候,我们设计的页面是左边的树结构没有数据,而在一张BOM单据保存建立之后,相应的页面左边的树结构将会把本BOM所对应的BOM母件和子件以及子件的BOM信息数据加载过来,并且在页面的左下部其BOM单据的母件图片也会显示出来(如图示12)。

 

图示1BOM新建时的页面显示状态)

 

图示2BOM保存后生成单据后页面树结构显示状态)

 

   另外,我们要在这里分析以下这个数的数据结构。首先从图示2中可以看到BOM树的根节点的文本是母件的品名和BOM版本号拼接起来的一个文本字符串,而子节点的文本是当前BOM下的所有子件品名信息,但是其中的子件文本信息还是有条件的显示的。如果这个子件单纯的是个子件的话,那就把子件品名信息文本显示出来就行了,且没有下级结点;而当该子件本身是一个BOM的是时候我们要分两种情况来判断他在当前BOM的显示状态,即:如果该子件的BOM有多个版本(两个或两个以上版本)的话,子件的显示状态是显示子件品名文本且该子节点有下级结点,那么这个子件的下级结点应该是该子件所有不同版本BOM的信息(该子件BOM信息也是由子件名称和相应的版本号拼接起来的);而如果该子件BOM只有一个版本的话呢,我们只需要把该子件BOM信息(由子件名称和相应的版本号拼接起来的文本)替代该子件的品名来显示(图示2就是这种情况)。

树的代码实现

首先,在ASPX页面上要用到EXT中的TreePanel控件,这个控件的属性以及相关事件的代码截图如:

图示2

从上面的截图看到,这棵树的根节点是一个异步树节点,而且在这个树控件上次根节点默认为不显示的;另外,在这棵树中好定义了一个BeforeLoad监听事件,这个事件的作用是加载当前树节点中其子节点的数据,而且吧这些数据装载到这棵树中。具体代码如下:

function nodeLoad(node) {//参数node是当前展开的节点对象

    var billid = document.getElementById('txtIdentityID').value;//BOM单据的BillID

    if (billid > 0) {

        var splitIndex = node.id.indexOf("_");//请注意树节点的数据结构:

        if (splitIndex == -1) {

//发送一次请求到服务器端进行数据处理

            Ext.net.DirectMethods.NodeLoad(billid, node.id, {

                success: function(result) {

                    var data = eval("(" + result + ")");

                    node.loadNodes(data);

                },

                failure: function(errorMsg) {

                    Ext.Msg.alert('Failure', errorMsg);

                }

            });

        }

        else {

            var splitstr = node.id.split("_");

            if (splitstr[0] == "1") {

//发送一次请求到服务器端进行数据处理

                Ext.net.DirectMethods.AddSubModules(splitstr[1], {

                    success: function(result) {

                        var data = eval("(" + result + ")");

                        node.loadNodes(data);

                    },

                    failure: function(errorMsg) {

                        Ext.Msg.alert('Failure', errorMsg);

                    }

                });

            }

            if (splitstr[0] == '11') {

//发送一次请求到服务器端进行数据处理

                Ext.net.DirectMethods.NodeLoad(splitstr[1], splitstr[1], {

                    success: function(result) {

                        var data = eval("(" + result + ")");

                        node.loadNodes(data);

                    },

                    failure: function(errorMsg) {

                        Ext.Msg.alert('Failure', errorMsg);

                    }

                });

            }

        }

    }

}

可以看到在这个方法中,有几次条件判断以及在不同条件下执行了不同的请求;这些条件是通过树节点的nodeId来建立的,nodeId的数据结构是这样子的:DOM根节点(DOM母件节点)的nodeID是此BOM单据的ID,而其子节点的nodeID是有多个字符串拼接起来的,具体可以看一下下面的服务器端代码(注意红色标记部分):

    #region 绑定Bom清单

    [DirectMethod]

    public string NodeLoad(int BomID, int nodeID)

    {

        string companyCD = ((UserInfoUtil)SessionUtil.Session["UserInfo"]).CompanyCD;

        BomModel model = new BomModel();

        model.CompanyCD = companyCD;

        model.ID = BomID;

        DataTable dt = BomBus.GetBomsInfoByID(model);

        Ext.Net.TreeNodeCollection nodes = new Ext.Net.TreeNodeCollection();

        if (dt.Rows.Count > 0)

        {

            string Bom_Nodeid = dt.Rows[0]["ID"].ToString();

            string strDateTime = DateTime.Now.ToString("yyyyMMddhhmmss");

            if (nodeID == 0)

            {

                Ext.Net.AsyncTreeNode asyncNode = new AsyncTreeNode();

                if (!string.IsNullOrEmpty(dt.Rows[0]["Verson"].ToString()))

                {

                    asyncNode.Text = dt.Rows[0]["ProductName"].ToString() + "(" + dt.Rows[0]["Verson"].ToString() + ")";

                }

                else

                {

                    asyncNode.Text = dt.Rows[0]["ProductName"].ToString();

                }

                asyncNode.NodeID = dt.Rows[0]["ID"].ToString();//BOM根节点的NODEID

                asyncNode.Listeners.Click.Handler = "LoadBomInfo(" + asyncNode.NodeID.ToString() + ",'checktree')";

                nodes.Add(asyncNode);

            }

            else

            {

                foreach (DataRow row in dt.Select("ID='0'"))

                {

                    Ext.Net.AsyncTreeNode asyncSubNode = new AsyncTreeNode();

                    if (row["IsBasicBom"].ToString() == "0")

                    {

                        asyncSubNode.Text = row["ProductName"].ToString();

                        asyncSubNode.NodeID = "0_" + row["ProductID"].ToString() + "_" + Bom_Nodeid + "_" + strDateTime;//一个子节点的NODEID

                        asyncSubNode.Leaf = true;

                        asyncSubNode.Listeners.Click.Handler = "LoadBomInfo(" + Bom_Nodeid.ToString() + ",'checktree')";

                    }

                    else

                    {

                        BomModel model1 = new BomModel();

                        model1.CompanyCD = companyCD;

                        model1.ProductID = row["ProductID"].ToString();

 

                        DataTable dt1 = BomBus.GetBomsByProductID(model1);

                        if (dt1.Rows.Count == 1)

                        {

                            if (!string.IsNullOrEmpty(dt1.Rows[0]["Verson"].ToString()))

                            {

                                asyncSubNode.Text = dt1.Rows[0]["ProductName"].ToString() + "(" + dt1.Rows[0]["Verson"].ToString() + ")";

                            }

                            else

                            {

                                asyncSubNode.Text = dt1.Rows[0]["ProductName"].ToString();

                            }

                            asyncSubNode.NodeID = "11_" + dt1.Rows[0]["ID"].ToString() + "_" + strDateTime;//子节点的NODEID

                            asyncSubNode.Listeners.Click.Handler = "LoadBomInfo(" + dt1.Rows[0]["ID"].ToString() + ",'checktree')";

                        }

                        else

                        {

                            asyncSubNode.Text = row["ProductName"].ToString();

                            asyncSubNode.NodeID = "1_" + row["ProductID"].ToString() + "_" + Bom_Nodeid + "_" + strDateTime;子节点的NODEID

 

                            asyncSubNode.Listeners.Click.Handler = "LoadBomInfo(" + Bom_Nodeid.ToString() + ",'checktree')";

                        }

                    }

                    nodes.Add(asyncSubNode);

                }

            }

        }

        return nodes.ToJson();

    }

    //递归

    [DirectMethod]

    public string AddSubModules(string productid)

    {

        string companyCD = ((UserInfoUtil)SessionUtil.Session["UserInfo"]).CompanyCD;

        Ext.Net.TreeNodeCollection nodes = new Ext.Net.TreeNodeCollection();

        string strDateTime = DateTime.Now.ToString("yyyyMMddhhmmss");

 

        BomModel model = new BomModel();

        model.CompanyCD = companyCD;

        model.ProductID = productid;

 

        DataTable dt = BomBus.GetBomsByProductID(model);

        //DataRow[] rows = userModules.Select("SuperDeptID = '" + moduleId + "'");

        foreach (DataRow row in dt.Rows)

        {

            Ext.Net.AsyncTreeNode asyncNode = new Ext.Net.AsyncTreeNode();

            if (!string.IsNullOrEmpty(row["Verson"].ToString()))

            {

                asyncNode.Text = row["ProductName"].ToString() + "(" + row["Verson"].ToString() + ")";

            }

            else

            {

                asyncNode.Text = row["ProductName"].ToString();

            }

            asyncNode.NodeID = "11_" + row["ID"].ToString() + "_" + strDateTime;

            asyncNode.Listeners.Click.Handler = "LoadBomInfo(" + row["ID"].ToString() + ",'checktree')";

            nodes.Add(asyncNode);

        }

        return nodes.ToJson();

    }

    #endregion

这些红色字体标记部分就是通过“标记_子件物品ID或子件BOMID_当前时间”的格式拼接起来的,这样的拼接可以保证个节点的NODEID是不一样的,并且“标记”元素的设计可以在JS的方法nodeLoad()中作为很好的判断条件,这个标记是这样设计的:当子件不是BOM时,标记=0;当子件只有一个版本BOM时,标记=11 而当子件有多个版本的BOM时,标记=1

    我们接着看上面这段代码。这段代码是获取DOM树中数据的一个方法,是和JS中的方法nodeLoad()相关联的,且看上面两段代码(jscs两部分代码)中标记为绿色字体部分,这部分代码是关联在一起的,首先在一定条件下JS端(浏览器端)可以分别通过一个请求直接调用了CS代码中的NodeLoad(int BomID, int nodeID)方法或者string AddSubModules(string productid)方法,这两个CS中的代码使用递归的方式来获取所需数据,之后返回到JS端(浏览器端)使其接收到数据后,使用node.loadNodes(data);来给树添加数据。

 

至此,整个BOM树的数据处理过程基本已经结束。其中的关键是对这棵树结构的理解。

 

转载于:https://www.cnblogs.com/xinzeda/archive/2011/09/01/2161903.html

### 回答1: 获取BOM(浏览器对象模型)的代码的实现方式有很多种,下面是一种常见的实现方式: ```javascript function getBomTree(node) { let tree = { name: node.nodeName, children: [] }; for (let i = 0; i < node.childNodes.length; i++) { let childNode = node.childNodes[i]; if (childNode.nodeType === 1) { // Element node tree.children.push(getBomTree(childNode)); } else if (childNode.nodeType === 3) { // Text node tree.children.push({ name: "TEXT", value: childNode.nodeValue }); } } return tree; } // 使用方法 let bomTree = getBomTree(document.documentElement); console.log(bomTree); ``` 上述代码中的`getBomTree`函数会遍历传入的节点及其子节点,创建一个包含节点信息的形结构。对于元素节点,会递归调用`getBomTree`函数;对于文本节点,会将节点值保存在`value`属性中。最后返回构建好的BOM。 调用`getBomTree`函数时,可以传入任意节点作为参数。一般情况下,可以将`document.documentElement`作为参数,它表示整个文档的根节点。获取到的`bomTree`对象将包含整个BOM的信息。 这只是一种实现方式,根据具体需求和使用场景的不同,可能需要对代码进行适当的修改和调整。 ### 回答2: 获取BOM的代码可以采用递归的方式遍历HTML文档,逐层获取每个节点的子节点,并将节点信息保存到一个列表中。 以下是一个示例代码: ``` def get_bom_tree(node): bom_tree = [] # 用于保存BOM的列表 children = node.childNodes # 获取当前节点的子节点列表 for child in children: if child.nodeType == child.ELEMENT_NODE: # 判断节点类型为元素节点 child_data = { 'tag': child.tagName, # 节点标签名 'attrs': dict(child.attributes.items()), # 节点属性 'children': get_bom_tree(child) # 递归获取子节点的BOM } bom_tree.append(child_data) return bom_tree # 示例用法 from xml.dom import minidom dom = minidom.parse('path/to/html/file') # 解析HTML文件 bom_tree = get_bom_tree(dom.documentElement) # 获取BOM # 打印BOM import json print(json.dumps(bom_tree, indent=4)) ``` 请注意,该代码使用了Python的内置库`xml.dom.minidom`来解析HTML文件,并递归获取BOM。在使用之前,需要安装`xml.dom`库,可以使用`pip install xml.dom`命令进行安装。 ### 回答3: 获取BOM(Browser Object Model)的代码可以通过JavaScript来实现。BOM是指代表浏览器窗口和窗口之间关系的状结构。在Web开发中,可以使用以下代码来获取BOM: ```javascript function getBomTree() { var currentWindow = window; // 获取当前窗口对象 var bomTree = { window: currentWindow, // 当前窗口对象为根节点 children: [] // 存储子窗口的数组 }; // 递归遍历子窗口 function traverseChildren(win, parentNode) { var iframes = win.document.getElementsByTagName('iframe'); // 获取当前窗口中的iframe元素 for (var i = 0; i < iframes.length; i++) { var iframeWindow = iframes[i].contentWindow; // 获取iframe窗口对象 var childNode = { window: iframeWindow, // 子窗口对象 children: [] // 存储子窗口的数组 }; parentNode.children.push(childNode); // 将子窗口节点添加到父节点的children数组中 traverseChildren(iframeWindow, childNode); // 递归遍历子窗口 } } traverseChildren(currentWindow, bomTree); // 调用递归函数遍历子窗口 return bomTree; } // 调用示例 var bomTree = getBomTree(); console.log(bomTree); ``` 以上代码通过递归函数`traverseChildren`来遍历子窗口,使用`getElementsByTagName`方法获取当前窗口中的所有`iframe`元素,然后获取其`contentWindow`属性来获取子窗口对象。通过递归调用,将所有子窗口对象存储在BOM中。最后通过`console.log`将BOM输出到控制台。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值